SHARE
TWEET

Untitled

a guest Mar 24th, 2016 88 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. diff --git a/lib/customize/pref.prf b/lib/customize/pref.prf
  2. index d6e32b2..0c6c082 100644
  3. --- a/lib/customize/pref.prf
  4. +++ b/lib/customize/pref.prf
  5. @@ -349,6 +349,9 @@ keymap-input:1:^C
  6.  # Message colors
  7.  %:message.prf
  8.  
  9. +# Message sounds
  10. +%:sound.prf
  11. +
  12.  ##### System Specific Subfiles #####
  13.  
  14.  ?:[EQU $SYS gcu]
  15. diff --git a/lib/customize/sound.prf b/lib/customize/sound.prf
  16. new file mode 100644
  17. index 0000000..3595a03
  18. --- /dev/null
  19. +++ b/lib/customize/sound.prf
  20. @@ -0,0 +1,513 @@
  21. +# sound.cfg
  22. +#
  23. +# Configuration file for the Angband sound events
  24. +#
  25. +# The format is:
  26. +# <event name>:<sample-names seperated by spaces>
  27. +#
  28. +# Example:
  29. +# hit:hit hit1
  30. +#
  31. +
  32. +#
  33. +# This is the Dubtrain Angband Sound config list, v.3.1.0 - February 24th, 2009
  34. +#
  35. +# Licensed under a Creative Commons non-commercial agreement
  36. +#
  37. +# Inspired by the original Craig's Angband Sound Patch.
  38. +#
  39. +# But with all new sounds.
  40. +#
  41. +# contact angband@dubtrain.com
  42. +#
  43. +# download zipped archive at www.dubtrain.com/angband
  44. +#
  45. +#
  46. +
  47. +
  48. +#
  49. +# Ambient sounds
  50. +#
  51. +
  52. +# Town during the day.
  53. +sound:AMBIENT_DAY:amb_thunder_rain
  54. +
  55. +# Town during the night.
  56. +sound:AMBIENT_NITE:amb_guitar_chord amb_thunder_roll
  57. +
  58. +# Dungeon levels 1-20 (50'-1000')
  59. +sound:AMBIENT_DNG1:amb_door_iron amb_bell_metal1
  60. +
  61. +# Dungeon levels 21-40 (1050'-2000')
  62. +sound:AMBIENT_DNG2:amb_bell_tibet1 amb_bell_metal2 amb_gong_strike
  63. +
  64. +# Dungeon levels 41-60 (2050'-3000')
  65. +sound:AMBIENT_DNG3:amb_bell_tibet2 amb_dungeon_echo amb_pulse_low
  66. +
  67. +# Dungeon levels 61-80 (3050'-4000')
  68. +sound:AMBIENT_DNG4:amb_bell_tibet3 amb_dungeon_echowet amb_gong_undertone
  69. +
  70. +# Dungeon levels 81 and beyond (4050'-)
  71. +sound:AMBIENT_DNG5:amb_door_doom amb_gong_chinese amb_gong_low
  72. +
  73. +#
  74. +# Store sounds
  75. +#
  76. +
  77. +# The shopkeep bought a worthless item.
  78. +sound:STORE1:sto_man_hey
  79. +
  80. +# The shopkeep paid too much for an item.
  81. +sound:STORE2:id_bad_dang
  82. +
  83. +# The shopkeep got away with a good bargain.
  84. +sound:STORE3:sto_man_haha
  85. +
  86. +# The shopkeep got away with a great bargain.
  87. +sound:STORE4:sto_man_whoohaha
  88. +
  89. +# You make a normal transaction (buying or selling).
  90. +sound:STORE5:sto_coins_countertop sto_bell_register1 sto_bell_register2
  91. +
  92. +# You enter a store.
  93. +sound:STORE_ENTER:sto_bell_desk sto_bell_ding sto_bell_dingaling sto_bell_jingles sto_bell_ringing sto_bell_shop
  94. +
  95. +# You enter your home.
  96. +sound:STORE_HOME:plm_door_entrance
  97. +
  98. +# You leave a store.
  99. +sound:STORE_LEAVE:plm_door_bolt
  100. +
  101. +#
  102. +# Player sounds - combat
  103. +#
  104. +
  105. +# You succeed in a melee attack against a monster.
  106. +sound:HIT:plc_hit_hay plc_hit_body
  107. +
  108. +# It was a good hit!
  109. +sound:HIT_GOOD:plc_hit_anvil
  110. +
  111. +# It was a great hit!
  112. +sound:HIT_GREAT:plc_hit_groan
  113. +
  114. +# It was a superb hit!
  115. +sound:HIT_SUPERB:plc_hit_grunt
  116. +
  117. +# It was a *GREAT* hit!
  118. +sound:HIT_HI_GREAT:plc_hit_grunt2
  119. +
  120. +# It was a *SUPERB* hit!
  121. +sound:HIT_HI_SUPERB:plc_hit_anvil2
  122. +
  123. +# You miss a melee attack against a monster.
  124. +sound:MISS:plc_miss_arrow2
  125. +
  126. +# You fire a missile.
  127. +sound:SHOOT:plc_miss_arrow
  128. +
  129. +# You hit something with a missile.
  130. +sound:SHOOT_HIT:plc_hit_arrow
  131. +
  132. +# You receive a hitpoint warning.
  133. +sound:HITPOINT_WARN:plc_bell_warn
  134. +
  135. +# You die.
  136. +sound:DEATH:plc_die_laugh
  137. +
  138. +#
  139. +# Player sounds - status changes
  140. +#
  141. +
  142. +# You become blind.
  143. +sound:BLIND:pls_tone_conk
  144. +
  145. +# You become confused.
  146. +sound:CONFUSED:pls_man_ugh
  147. +
  148. +# You become poisoned.
  149. +sound:POISONED:pls_tone_guiro
  150. +
  151. +# You become afraid.
  152. +sound:AFRAID:pls_man_yell
  153. +
  154. +# You become paralyzed.
  155. +sound:PARALYZED:pls_man_gulp_new
  156. +
  157. +# You feel drugged (chaos effects).
  158. +sound:DRUGGED:pls_breathe_in
  159. +
  160. +# You become slower.
  161. +sound:SLOW:pls_man_sigh
  162. +
  163. +# You become stunned.
  164. +sound:STUN:pls_bell_mute
  165. +
  166. +# You suffer a cut.
  167. +sound:CUT:pls_man_argoh
  168. +
  169. +# A stat is drained
  170. +sound:DRAIN_STAT:pls_tone_headstock
  171. +
  172. +# You recover from a condition (blind, confused, etc.)
  173. +sound:RECOVER:pls_bell_chime_new
  174. +
  175. +# You become faster.
  176. +sound:SPEED:pls_bell_sustain
  177. +
  178. +# You attain a mystic shield.
  179. +sound:SHIELD:pls_bell_bowl
  180. +
  181. +# You become blessed.
  182. +sound:BLESSED:sum_angel_song
  183. +
  184. +# You feel heroic.
  185. +sound:HERO:pls_tone_goblet
  186. +
  187. +# You are bold.
  188. +sound:BOLD:pls_bell_hibell_soft
  189. +
  190. +# You become berserk.
  191. +sound:BERSERK:pls_man_scream2
  192. +
  193. +# You feel protected from evil.
  194. +sound:PROT_EVIL:pls_bell_glass
  195. +
  196. +# You feel invulnerable. (does any item/spell do this anymore?)
  197. +sound:INVULN:pls_tone_blurk
  198. +
  199. +# You can see invisible things.
  200. +sound:SEE_INVIS:pls_tone_clave6
  201. +
  202. +# You can see the infrared spectrum
  203. +sound:INFRARED:pls_tone_clavelo8
  204. +
  205. +# You become resistant to acid.
  206. +sound:RES_ACID:pls_man_sniff
  207. +
  208. +# You become resistant to electricity.
  209. +sound:RES_ELEC:pls_tone_elec
  210. +
  211. +# You become resistant to fire.
  212. +sound:RES_FIRE:pls_tone_scrape
  213. +
  214. +# You become resistant to cold.
  215. +sound:RES_COLD:pls_tone_stick
  216. +
  217. +# You become resistant to poison.
  218. +sound:RES_POIS:pls_man_spit
  219. +
  220. +# You become hungry.
  221. +sound:HUNGRY:pls_man_sob
  222. +
  223. +#
  224. +# Player sounds - misc.
  225. +#
  226. +
  227. +# You pick up money worth less than 200 au.
  228. +sound:MONEY1:plm_coins_light plm_coins_shake
  229. +
  230. +# You pick up money worth between 200 and 600 au.
  231. +sound:MONEY2:plm_chain_light plm_coins_pour
  232. +
  233. +# You pick up money worth 600 au or more.
  234. +sound:MONEY3:plm_coins_dump
  235. +
  236. +# You (or a monster) drop something on the ground.
  237. +sound:DROP:plm_drop_boot
  238. +
  239. +# You gain (or regain) a level.
  240. +sound:LEVEL:plm_levelup
  241. +
  242. +# You successfully study a spell or prayer.
  243. +sound:STUDY:plm_book_pageturn
  244. +
  245. +# You teleport or phase door.
  246. +sound:TELEPORT:plm_chimes_jangle
  247. +
  248. +# You quaff a potion.
  249. +sound:QUAFF:plm_bottle_clinks plm_cork_pop plm_cork_squeak
  250. +
  251. +# You zap a rod.
  252. +sound:ZAP_ROD:plm_zap_rod
  253. +
  254. +# You take a step.  (unimplemented)
  255. +# walk:
  256. +
  257. +# You teleport someone else away.
  258. +sound:TPOTHER:plm_chimes_jangle
  259. +
  260. +# You bump into a wall or door.
  261. +sound:HITWALL:plm_wood_thud
  262. +
  263. +# You eat something.
  264. +sound:EAT:plm_eat_bite
  265. +
  266. +# You successfully dig through something.
  267. +sound:DIG:plm_metal_clank
  268. +
  269. +# You open a door.
  270. +sound:OPENDOOR:plm_door_bolt plm_door_creak plm_door_dungeon plm_door_entrance plm_door_open plm_door_opening plm_door_rusty plm_door_squeaky
  271. +
  272. +# You shut a door.
  273. +sound:SHUTDOOR:plm_bang_dumpster plm_cabinet_shut plm_close_hatch plm_door_creakshut plm_door_latch plm_door_shut plm_door_slam
  274. +
  275. +# You teleport from a level (including via recall).
  276. +sound:TPLEVEL:sum_bell_crystal
  277. +
  278. +# Default "bell" sound for system messages.
  279. +sound:BELL:plm_jar_ding
  280. +
  281. +# You try to open something that's not a door.
  282. +sound:NOTHING_TO_OPEN:plm_click_switch2 plm_door_knob
  283. +
  284. +# You fail to pick a lock.
  285. +sound:LOCKPICK_FAIL:plm_click_dry plm_click_switch plm_click_wood plm_door_echolock plm_door_wooden
  286. +
  287. +# You pick a lock.
  288. +sound:LOCKPICK:plm_break_wood plm_cabinet_open plm_chest_unlatch plm_lock_case plm_lock_distant plm_open_case
  289. +
  290. +# You disarm a trap.
  291. +sound:DISARM:plm_bang_ceramic plm_chest_latch plm_click_switch3
  292. +
  293. +# You go up stairs.
  294. +sound:STAIRS_UP:plm_floor_creak2
  295. +
  296. +# You go down stairs.
  297. +sound:STAIRS_DOWN:plm_floor_creak
  298. +
  299. +# You activate an artifact.
  300. +sound:ACT_ARTIFACT:plm_aim_wand
  301. +
  302. +# You use a staff.
  303. +sound:USE_STAFF:plm_use_staff
  304. +
  305. +# An object is destroyed.
  306. +sound:DESTROY:plm_bang_metal plm_break_canister plm_break_glass plm_break_glass2 plm_break_plates plm_break_shatter plm_break_smash plm_glass_breaking plm_glass_break plm_glass_smashing
  307. +
  308. +# You wield or take off something.
  309. +sound:WIELD:plm_metal_sharpen
  310. +
  311. +# You take something in or out of your quiver.
  312. +sound:QUIVER:plc_miss_swish
  313. +
  314. +# You wield a cursed item.
  315. +sound:CURSED:pls_man_oooh
  316. +
  317. +# You notice something (generic notice)
  318. +sound:NOTICE:id_bad_hmm
  319. +
  320. +# You notice something about your equipment or inventory.
  321. +sound:PSEUDOID:id_good_hmm
  322. +
  323. +# You successfully cast a spell.
  324. +sound:SPELL:plm_spell1 plm_spell2 plm_spell3
  325. +
  326. +# You successfully pray a prayer.
  327. +sound:PRAYER:sum_angel_song
  328. +
  329. +#
  330. +# Monster Sounds - combat
  331. +#
  332. +
  333. +# A monster flees in terror.
  334. +sound:FLEE:mco_creature_yelp
  335. +
  336. +# A monster is killed.
  337. +sound:KILL:mco_howl_croak mco_howl_deep mco_howl_distressed mco_howl_high mco_howl_long
  338. +
  339. +# A unique is killed.
  340. +sound:KILL_UNIQUE:sum_ghost_wail
  341. +
  342. +# Morgoth, Lord of Darkness is killed.
  343. +sound:KILL_KING:amb_guitar_chord
  344. +
  345. +# Attack - hit
  346. +sound:MON_HIT:mco_hit_whip
  347. +
  348. +# Attack - touch
  349. +sound:MON_TOUCH:mco_click_vibra
  350. +
  351. +# Attack - punch
  352. +sound:MON_PUNCH:mco_squish_snap
  353. +
  354. +# Attack - kick
  355. +sound:MON_KICK:mco_rubber_thud
  356. +
  357. +# Attack - claw
  358. +sound:MON_CLAW:mco_ceramic_trill mco_scurry_dry
  359. +
  360. +# Attack - bite
  361. +sound:MON_BITE:mco_snarl_short mco_bite_soft mco_bite_munch mco_bite_long mco_bite_short mco_bite_gnash mco_bite_chomp mco_bite_regular mco_bite_small mco_bite_dainty mco_bite_hard mco_bite_chew
  362. +
  363. +# Attack - sting
  364. +sound:MON_STING:mco_castanet_trill mco_tube_hit
  365. +
  366. +# Attack - butt
  367. +sound:MON_BUTT:mco_cuica_rubbing mco_thud_crash
  368. +
  369. +# Attack - crush
  370. +sound:MON_CRUSH:mco_dino_low mco_squish_hit
  371. +
  372. +# Attack - engulf
  373. +sound:MON_ENGULF:mco_dino_talk mco_dino_yawn
  374. +
  375. +# Attack - crawl
  376. +sound:MON_CRAWL:mco_card_shuffle mco_shake_roll
  377. +
  378. +# Attack - drool
  379. +sound:MON_DROOL:mco_creature_choking mco_liquid_squirt
  380. +
  381. +# Attack - spit
  382. +sound:MON_SPIT:mco_attack_spray
  383. +
  384. +# Attack - gaze
  385. +sound:MON_GAZE:mco_thoing_backwards
  386. +
  387. +# Attack - wail
  388. +sound:MON_WAIL:mco_dino_low
  389. +
  390. +# Attack - release spores
  391. +sound:MON_SPORE:mco_dub_wobble mco_spray_long
  392. +
  393. +# Attack - beg for money
  394. +sound:MON_BEG:mco_man_mumble
  395. +
  396. +# Attack - insult
  397. +sound:MON_INSULT:mco_strange_thwoink
  398. +
  399. +# Attack - moan
  400. +sound:MON_MOAN:mco_strange_music
  401. +
  402. +# Attack - shriek
  403. +sound:SHRIEK:mco_mouse_squeaks
  404. +
  405. +# Spell - create traps
  406. +sound:CREATE_TRAP:mco_thoing_deep
  407. +
  408. +# Spell - cause fear
  409. +sound:CAST_FEAR:mco_creature_groan mco_dino_slur
  410. +
  411. +# Multiply (breed explosively)
  412. +sound:MULTIPLY:mco_frog_trill
  413. +
  414. +#
  415. +# Summons
  416. +#
  417. +
  418. +# Summon one or more monsters.
  419. +sound:SUM_MONSTER:sum_chime_jangle
  420. +
  421. +# Summon angels.
  422. +sound:SUM_AINU:sum_angel_song
  423. +
  424. +# Summon undead.
  425. +sound:SUM_UNDEAD:sum_ghost_oooo
  426. +
  427. +# Summon animals.
  428. +sound:SUM_ANIMAL:sum_lion_growl
  429. +
  430. +# Summon spiders.
  431. +sound:SUM_SPIDER:sum_piano_scrape
  432. +
  433. +# Summon hounds.
  434. +sound:SUM_HOUND:sum_lion_growl
  435. +
  436. +# Summon hydras.
  437. +sound:SUM_HYDRA:sum_piano_scrape
  438. +
  439. +# Summon demons.
  440. +sound:SUM_DEMON:sum_ghost_wail sum_laugh_evil2
  441. +
  442. +# Summon dragon.
  443. +sound:SUM_DRAGON:sum_piano_scrape
  444. +
  445. +# Summon greater undead.
  446. +sound:SUM_HI_UNDEAD:sum_ghost_moan
  447. +
  448. +# Summon greater dragons.
  449. +sound:SUM_HI_DRAGON:sum_gong_temple
  450. +
  451. +# Summon greater demons.
  452. +sound:SUM_HI_DEMON:sum_ghost_moan
  453. +
  454. +# Summon Ringwraiths.
  455. +sound:SUM_WRAITH:sum_bell_hand
  456. +
  457. +# Summon uniques.
  458. +sound:SUM_UNIQUE:sum_bell_tone
  459. +
  460. +#
  461. +# Breath weapons
  462. +#
  463. +
  464. +# Breathe frost.
  465. +sound:BR_FROST:mco_attack_breath
  466. +
  467. +# Breathe electricity.
  468. +MST_BR_ELEC:mco_attack_breath
  469. +
  470. +# Breathe acid.
  471. +sound:BR_ACID:mco_attack_breath
  472. +
  473. +# Breathe gas.
  474. +sound:BR_GAS:mco_attack_breath
  475. +
  476. +# Breathe fire.
  477. +sound:BR_FIRE:mco_attack_breath
  478. +
  479. +# Breathe disenchantment.
  480. +sound:BR_DISEN:mco_attack_breath
  481. +
  482. +# Breathe chaos.
  483. +sound:BR_CHAOS:mco_attack_breath
  484. +
  485. +# Breathe shards.
  486. +sound:BR_SHARDS:mco_attack_breath
  487. +
  488. +# Breathe sound.
  489. +sound:BR_SOUND:mco_attack_breath
  490. +
  491. +# Breathe light.
  492. +sound:BR_LIGHT:mco_attack_breath
  493. +
  494. +# Breathe darkness.
  495. +sound:BR_DARK:mco_attack_breath
  496. +
  497. +# Breathe nether.
  498. +sound:BR_NETHER:mco_attack_breath
  499. +
  500. +# Breathe nexus.
  501. +sound:BR_NEXUS:mco_attack_breath
  502. +
  503. +# Breathe time.
  504. +sound:BR_TIME:mco_attack_breath
  505. +
  506. +# Breathe inertia.
  507. +sound:BR_INERTIA:mco_attack_breath
  508. +
  509. +# Breathe gravity.
  510. +sound:BR_GRAVITY:mco_attack_breath
  511. +
  512. +# Breathe plasma.
  513. +sound:BR_PLASMA:mco_attack_breath
  514. +
  515. +# Breathe force.
  516. +sound:BR_FORCE:mco_attack_breath
  517. +
  518. +# Breathe the elements (power dragon scale mail).
  519. +sound:BR_ELEMENTS:mco_attack_breath
  520. +
  521. +#
  522. +# Identifying Items
  523. +#
  524. +
  525. +# Identify a bad item (including bad ego items and artifacts).
  526. +sound:IDENT_BAD:id_bad_aww id_bad_dang id_bad_hmm id_bad_hmph id_bad_ohh
  527. +
  528. +# Identify a good ego item.
  529. +sound:IDENT_EGO:id_ego_whoa id_ego_woohoo id_ego_yeah id_ego_yeah2 id_ego_yes
  530. +
  531. +# Identify a good artifact.
  532. +sound:IDENT_ART:id_good_hey id_good_hey2 id_good_hmm id_good_huh id_good_ooh id_good_ooo id_good_wow
  533. +
  534. diff --git a/src/Makefile.src b/src/Makefile.src
  535. index 5d4a738..c4296f9 100644
  536. --- a/src/Makefile.src
  537. +++ b/src/Makefile.src
  538. @@ -158,6 +158,7 @@ ANGFILES = \
  539.     score.o \
  540.     save.o \
  541.     savefile.o \
  542. +   sound-core.o \
  543.     store.o \
  544.     target.o \
  545.     trap.o \
  546. diff --git a/src/avltree.h b/src/avltree.h
  547. new file mode 100644
  548. index 0000000..f3c5977
  549. --- /dev/null
  550. +++ b/src/avltree.h
  551. @@ -0,0 +1,212 @@
  552. +/* tree.h -- AVL trees (in the spirit of BSD's 'queue.h')  -*- C -*-   */
  553. +
  554. +/* Copyright (c) 2005 Ian Piumarta
  555. + *
  556. + * All rights reserved.
  557. + *
  558. + * Permission is hereby granted, free of charge, to any person obtaining a copy
  559. + * of this software and associated documentation files (the 'Software'), to deal
  560. + * in the Software without restriction, including without limitation the rights
  561. + * to use, copy, modify, merge, publish, distribute, and/or sell copies of the
  562. + * Software, and to permit persons to whom the Software is furnished to do so,
  563. + * provided that the above copyright notice(s) and this permission notice appear
  564. + * in all copies of the Software and that both the above copyright notice(s) and
  565. + * this permission notice appear in supporting documentation.
  566. + *
  567. + * THE SOFTWARE IS PROVIDED 'AS IS'.  USE ENTIRELY AT YOUR OWN RISK.
  568. + */
  569. +
  570. +/* This file defines an AVL balanced binary tree [Georgii M. Adelson-Velskii and
  571. + * Evgenii M. Landis, 'An algorithm for the organization of information',
  572. + * Doklady Akademii Nauk SSSR, 146:263-266, 1962 (Russian).  Also in Myron
  573. + * J. Ricci (trans.), Soviet Math, 3:1259-1263, 1962 (English)].
  574. + *
  575. + * An AVL tree is headed by pointers to the root node and to a function defining
  576. + * the ordering relation between nodes.  Each node contains an arbitrary payload
  577. + * plus three fields per tree entry: the depth of the subtree for which it forms
  578. + * the root and two pointers to child nodes (singly-linked for minimum space, at
  579. + * the expense of direct access to the parent node given a pointer to one of the
  580. + * children).  The tree is rebalanced after every insertion or removal.  The
  581. + * tree may be traversed in two directions: forward (in-order left-to-right) and
  582. + * reverse (in-order, right-to-left).
  583. + *
  584. + * Because of the recursive nature of many of the operations on trees it is
  585. + * necessary to define a number of helper functions for each type of tree node.
  586. + * The macro TREE_DEFINE(node_tag, entry_name) defines these functions with
  587. + * unique names according to the node_tag.  This macro should be invoked,
  588. + * thereby defining the necessary functions, once per node tag in the program.
  589. + *
  590. + * For details on the use of these macros, see the tree(3) manual page.
  591. + */
  592. +
  593. +#ifndef __tree_h
  594. +#define __tree_h
  595. +
  596. +
  597. +#define TREE_DELTA_MAX 1
  598. +
  599. +#define TREE_ENTRY(type)           \
  600. +  struct {                 \
  601. +    struct type    *avl_left;          \
  602. +    struct type    *avl_right;         \
  603. +    int         avl_height;            \
  604. +  }
  605. +
  606. +#define TREE_HEAD(name, type)              \
  607. +  struct name {                        \
  608. +    struct type *th_root;              \
  609. +    int  (*th_cmp)(struct type *lhs, struct type *rhs);    \
  610. +  }
  611. +
  612. +#define TREE_INITIALIZER(cmp) { 0, cmp }
  613. +
  614. +#define TREE_DELTA(self, field)                                \
  615. +  (( (((self)->field.avl_left)  ? (self)->field.avl_left->field.avl_height  : 0))  \
  616. +   - (((self)->field.avl_right) ? (self)->field.avl_right->field.avl_height : 0))
  617. +
  618. +/* Recursion prevents the following from being defined as macros. */
  619. +
  620. +#define TREE_DEFINE(node, field)                                   \
  621. +                                                   \
  622. +  struct node *TREE_BALANCE_##node##_##field(struct node *);                       \
  623. +                                                   \
  624. +  struct node *TREE_ROTL_##node##_##field(struct node *self)                       \
  625. +  {                                                    \
  626. +    struct node *r= self->field.avl_right;                             \
  627. +    self->field.avl_right= r->field.avl_left;                              \
  628. +    r->field.avl_left= TREE_BALANCE_##node##_##field(self);                        \
  629. +    return TREE_BALANCE_##node##_##field(r);                               \
  630. +  }                                                    \
  631. +                                                   \
  632. +  struct node *TREE_ROTR_##node##_##field(struct node *self)                       \
  633. +  {                                                    \
  634. +    struct node *l= self->field.avl_left;                              \
  635. +    self->field.avl_left= l->field.avl_right;                              \
  636. +    l->field.avl_right= TREE_BALANCE_##node##_##field(self);                       \
  637. +    return TREE_BALANCE_##node##_##field(l);                               \
  638. +  }                                                    \
  639. +                                                   \
  640. +  struct node *TREE_BALANCE_##node##_##field(struct node *self)                        \
  641. +  {                                                    \
  642. +    int delta= TREE_DELTA(self, field);                                    \
  643. +                                                   \
  644. +    if (delta < -TREE_DELTA_MAX)                                   \
  645. +      {                                                    \
  646. +   if (TREE_DELTA(self->field.avl_right, field) > 0)                       \
  647. +     self->field.avl_right= TREE_ROTR_##node##_##field(self->field.avl_right);         \
  648. +   return TREE_ROTL_##node##_##field(self);                            \
  649. +      }                                                    \
  650. +    else if (delta > TREE_DELTA_MAX)                                   \
  651. +      {                                                    \
  652. +   if (TREE_DELTA(self->field.avl_left, field) < 0)                        \
  653. +     self->field.avl_left= TREE_ROTL_##node##_##field(self->field.avl_left);           \
  654. +   return TREE_ROTR_##node##_##field(self);                            \
  655. +      }                                                    \
  656. +    self->field.avl_height= 0;                                     \
  657. +    if (self->field.avl_left && (self->field.avl_left->field.avl_height > self->field.avl_height)) \
  658. +      self->field.avl_height= self->field.avl_left->field.avl_height;                  \
  659. +    if (self->field.avl_right && (self->field.avl_right->field.avl_height > self->field.avl_height))   \
  660. +      self->field.avl_height= self->field.avl_right->field.avl_height;                 \
  661. +    self->field.avl_height += 1;                                   \
  662. +    return self;                                           \
  663. +  }                                                    \
  664. +                                                   \
  665. +  struct node *TREE_INSERT_##node##_##field                                \
  666. +    (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs))      \
  667. +  {                                                    \
  668. +    if (!self)                                             \
  669. +      return elm;                                          \
  670. +    if (compare(elm, self) < 0)                                        \
  671. +      self->field.avl_left= TREE_INSERT_##node##_##field(self->field.avl_left, elm, compare);      \
  672. +    else                                               \
  673. +      self->field.avl_right= TREE_INSERT_##node##_##field(self->field.avl_right, elm, compare);        \
  674. +    return TREE_BALANCE_##node##_##field(self);                                \
  675. +  }                                                    \
  676. +                                                   \
  677. +  struct node *TREE_FIND_##node##_##field                              \
  678. +    (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs))      \
  679. +  {                                                    \
  680. +    if (!self)                                             \
  681. +      return 0;                                                \
  682. +    if (compare(elm, self) == 0)                                   \
  683. +      return self;                                         \
  684. +    if (compare(elm, self) < 0)                                        \
  685. +      return TREE_FIND_##node##_##field(self->field.avl_left, elm, compare);               \
  686. +    else                                               \
  687. +      return TREE_FIND_##node##_##field(self->field.avl_right, elm, compare);              \
  688. +  }                                                    \
  689. +                                                   \
  690. +  struct node *TREE_MOVE_RIGHT_##node##_##field(struct node *self, struct node *rhs)                   \
  691. +  {                                                    \
  692. +    if (!self)                                             \
  693. +      return rhs;                                          \
  694. +    self->field.avl_right= TREE_MOVE_RIGHT_##node##_##field(self->field.avl_right, rhs);                   \
  695. +    return TREE_BALANCE_##node##_##field(self);                                \
  696. +  }                                                    \
  697. +                                                   \
  698. +  struct node *TREE_REMOVE_##node##_##field                                \
  699. +    (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs))      \
  700. +  {                                                    \
  701. +    if (!self) return 0;                                       \
  702. +                                                   \
  703. +    if (compare(elm, self) == 0)                                   \
  704. +      {                                                    \
  705. +   struct node *tmp= TREE_MOVE_RIGHT_##node##_##field(self->field.avl_left, self->field.avl_right);            \
  706. +   self->field.avl_left= 0;                                    \
  707. +   self->field.avl_right= 0;                                   \
  708. +   return tmp;                                         \
  709. +      }                                                    \
  710. +    if (compare(elm, self) < 0)                                        \
  711. +      self->field.avl_left= TREE_REMOVE_##node##_##field(self->field.avl_left, elm, compare);      \
  712. +    else                                               \
  713. +      self->field.avl_right= TREE_REMOVE_##node##_##field(self->field.avl_right, elm, compare);        \
  714. +    return TREE_BALANCE_##node##_##field(self);                                \
  715. +  }                                                    \
  716. +                                                   \
  717. +  void TREE_FORWARD_APPLY_ALL_##node##_##field                             \
  718. +    (struct node *self, void (*function)(struct node *node, void *data), void *data)           \
  719. +  {                                                    \
  720. +    if (self)                                              \
  721. +      {                                                    \
  722. +   TREE_FORWARD_APPLY_ALL_##node##_##field(self->field.avl_left, function, data);          \
  723. +   function(self, data);                                       \
  724. +   TREE_FORWARD_APPLY_ALL_##node##_##field(self->field.avl_right, function, data);         \
  725. +      }                                                    \
  726. +  }                                                    \
  727. +                                                   \
  728. +  void TREE_REVERSE_APPLY_ALL_##node##_##field                             \
  729. +    (struct node *self, void (*function)(struct node *node, void *data), void *data)           \
  730. +  {                                                    \
  731. +    if (self)                                              \
  732. +      {                                                    \
  733. +   TREE_REVERSE_APPLY_ALL_##node##_##field(self->field.avl_right, function, data);         \
  734. +   function(self, data);                                       \
  735. +   TREE_REVERSE_APPLY_ALL_##node##_##field(self->field.avl_left, function, data);          \
  736. +      }                                                    \
  737. +  }
  738. +
  739. +#define TREE_INSERT(head, node, field, elm)                        \
  740. +  ((head)->th_root= TREE_INSERT_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
  741. +
  742. +#define TREE_FIND(head, node, field, elm)              \
  743. +  (TREE_FIND_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
  744. +
  745. +#define TREE_REMOVE(head, node, field, elm)                        \
  746. +  ((head)->th_root= TREE_REMOVE_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
  747. +
  748. +#define TREE_DEPTH(head, field)            \
  749. +  ((head)->th_root->field.avl_height)
  750. +
  751. +#define TREE_FORWARD_APPLY(head, node, field, function, data)  \
  752. +  TREE_FORWARD_APPLY_ALL_##node##_##field((head)->th_root, function, data)
  753. +
  754. +#define TREE_REVERSE_APPLY(head, node, field, function, data)  \
  755. +  TREE_REVERSE_APPLY_ALL_##node##_##field((head)->th_root, function, data)
  756. +
  757. +#define TREE_INIT(head, cmp) do {      \
  758. +    (head)->th_root= 0;                \
  759. +    (head)->th_cmp= (cmp);         \
  760. +  } while (0)
  761. +
  762. +
  763. +#endif /* __tree_h */
  764. diff --git a/src/main.c b/src/main.c
  765. index 6717e0e..948a852 100644
  766. --- a/src/main.c
  767. +++ b/src/main.c
  768. @@ -43,6 +43,8 @@
  769.  
  770.  #include "main.h"
  771.  
  772. +#include "sound.h"
  773. +
  774.  /**
  775.   * List of the available modules in the order they are tried.
  776.   */
  777. @@ -69,22 +71,6 @@ static const struct module modules[] =
  778.  #endif /* USE_STATS */
  779.  };
  780.  
  781. -static int init_sound_dummy(int argc, char *argv[]) {
  782. -   return 0;
  783. -}
  784. -
  785. -/**
  786. - * List of sound modules in the order they should be tried.
  787. - */
  788. -static const struct module sound_modules[] =
  789. -{
  790. -#ifdef SOUND_SDL
  791. -   { "sdl", "SDL_mixer sound module", init_sound_sdl },
  792. -#endif /* SOUND_SDL */
  793. -
  794. -   { "none", "No sound", init_sound_dummy },
  795. -};
  796. -
  797.  /**
  798.   * A hook for "quit()".
  799.   *
  800. @@ -467,9 +453,7 @@ int main(int argc, char *argv[])
  801.                 }
  802.                 puts("                 Multiple -d options are allowed.");
  803.                 puts("  -s<mod>        Use sound module <sys>:");
  804. -               for (i = 0; i < (int)N_ELEMENTS(sound_modules); i++)
  805. -                   printf("     %s   %s\n", sound_modules[i].name,
  806. -                          sound_modules[i].help);
  807. +               print_sound_help();
  808.                 puts("  -m<sys>        Use module <sys>, where <sys> can be:");
  809.  
  810.                 /* Print the name and help for each available module */
  811. @@ -532,12 +516,6 @@ int main(int argc, char *argv[])
  812.  
  813.  #endif /* UNIX */
  814.  
  815. -   /* Try the modules in the order specified by sound_modules[] */
  816. -   for (i = 0; i < (int)N_ELEMENTS(sound_modules); i++)
  817. -       if (!soundstr || streq(soundstr, sound_modules[i].name))
  818. -           if (0 == sound_modules[i].init(argc, argv))
  819. -               break;
  820. -
  821.     /* Catch nasty signals */
  822.     signals_init();
  823.  
  824. @@ -549,6 +527,10 @@ int main(int argc, char *argv[])
  825.     init_angband();
  826.     textui_init();
  827.  
  828. +   /* Initialise sound */
  829. +   if (0 != init_sound(soundstr, argc, argv))
  830. +       plog("Failed to initialize sound!");    /* Non-fatal */
  831. +
  832.     /* Wait for response */
  833.     pause_line(Term);
  834.  
  835. diff --git a/src/main.h b/src/main.h
  836. index 70c11e0..39d442b 100644
  837. --- a/src/main.h
  838. +++ b/src/main.h
  839. @@ -23,9 +23,6 @@
  840.  #include "angband.h"
  841.  #include "ui-term.h"
  842.  
  843. -extern errr init_sound_sdl(int argc, char **argv);
  844. -
  845. -
  846.  extern errr init_lfb(int argc, char **argv);
  847.  extern errr init_x11(int argc, char **argv);
  848.  extern errr init_xpj(int argc, char **argv);
  849. diff --git a/src/message.h b/src/message.h
  850. index d08a8e6..1474fa3 100644
  851. --- a/src/message.h
  852. +++ b/src/message.h
  853. @@ -34,7 +34,7 @@ enum {
  854.  /* Functions */
  855.  void messages_init(void);
  856.  void messages_free(void);
  857. -u16b messages_num(void);  
  858. +u16b messages_num(void);
  859.  void message_add(const char *str, u16b type);
  860.  const char *message_str(u16b age);
  861.  u16b message_count(u16b age);
  862. diff --git a/src/snd-sdl.c b/src/snd-sdl.c
  863. index afce53f..de9c04d 100644
  864. --- a/src/snd-sdl.c
  865. +++ b/src/snd-sdl.c
  866. @@ -4,6 +4,7 @@
  867.   *
  868.   * Copyright (c) 2004 Brendon Oliver <brendon.oliver@gmail.com>
  869.   * Copyright (c) 2007 Andi Sidwell <andi@takkaria.org>
  870. + * Copyright (c) 2016 Graeme Russ <graeme.russ@gmail.com>
  871.   * A large chunk of this file was taken and modified from main-ros.
  872.   *
  873.   * This work is free software; you can redistribute it and/or modify it
  874. @@ -19,86 +20,52 @@
  875.   */
  876.  #include "angband.h"
  877.  #include "init.h"
  878. -
  879. +#include "sound.h"
  880. +
  881.  #ifdef SOUND_SDL
  882.  
  883.  
  884.  #include "SDL.h"
  885.  #include "SDL_mixer.h"
  886.  
  887. -
  888. -/**
  889. - * Don't cache audio
  890. - */
  891. -static bool no_cache_audio = false;
  892. -
  893. -/**
  894. - * Using mp3s
  895. - */
  896. -static bool use_mp3 = false;
  897. -
  898. -/**
  899. - * Arbitary limit on number of samples per event
  900. - */
  901. -#define MAX_SAMPLES      16
  902. +typedef enum sdl_sample_type {
  903. +   SDL_CHUNK,
  904. +   SDL_MUSIC,
  905. +   SDL_NULL
  906. +} sdl_sample_type;
  907.  
  908.  /**
  909.   * Struct representing all data about an event sample
  910.   */
  911.  typedef struct
  912.  {
  913. -   int num;                        /* Number of samples for this event */
  914. -   Mix_Chunk *wavs[MAX_SAMPLES];   /* Sample array */
  915. -   Mix_Music *mp3s[MAX_SAMPLES];   /* Sample array */
  916. -   char *paths[MAX_SAMPLES]; /* Relative pathnames for samples */
  917. -} sample_list;
  918. -
  919. -
  920. -/**
  921. - * Just need an array of SampInfos
  922. - */
  923. -static sample_list samples[MSG_MAX];
  924. -
  925. -
  926. -/**
  927. - * Shut down the sound system and free resources.
  928. - */
  929. -static void close_audio(void)
  930. -{
  931. -   size_t i;
  932. -   int j;
  933. -
  934. -   /* Free all the sample data*/
  935. -   for (i = 0; i < MSG_MAX; i++) {
  936. -       sample_list *smp = &samples[i];
  937. -
  938. -       /* Nuke all samples */
  939. -       for (j = 0; j < smp->num; j++) {
  940. -           if (use_mp3)
  941. -               Mix_FreeMusic(smp->mp3s[j]);
  942. -           else
  943. -               Mix_FreeChunk(smp->wavs[j]);
  944. -           string_free(smp->paths[j]);
  945. -       }
  946. -   }
  947. -
  948. -   /* Close the audio */
  949. -   Mix_CloseAudio();
  950. -
  951. -   /* XXX This may conflict with the SDL port */
  952. -   SDL_Quit();
  953. -}
  954. -
  955. -
  956. +   union {
  957. +       Mix_Chunk *chunk;   /* Sample in WAVE format */
  958. +       Mix_Music *music;   /* Sample in MP3 format */
  959. +   } sample_data;
  960. +
  961. +   sdl_sample_type sample_type;
  962. +   char *path;         /* Relative pathnames for samples */
  963. +} sdl_sample;
  964. +
  965. +typedef struct sdl_file_type {
  966. +   const char *extension;
  967. +   sdl_sample_type type;
  968. +} sdl_file_type_t;
  969. +
  970. +/* List of supported file types */
  971. +static const sdl_file_type_t supported_file_types[] = { {".mp3", SDL_MUSIC},
  972. +                           {".ogg", SDL_CHUNK},
  973. +                           {"", SDL_NULL} };
  974.  /**
  975. - * Initialise SDL and open the mixer
  976. + * Initialise SDL and open the mixer.
  977.   */
  978. -static bool open_audio(void)
  979. +static bool open_audio_sdl(int argc, char **argv)
  980.  {
  981.     int audio_rate;
  982.     Uint16 audio_format;
  983.     int audio_channels;
  984. -  
  985. +
  986.     /* Initialize variables */
  987.     audio_rate = 22050;
  988.     audio_format = AUDIO_S16;
  989. @@ -106,13 +73,13 @@ static bool open_audio(void)
  990.  
  991.     /* Initialize the SDL library */
  992.     if (SDL_Init(SDL_INIT_AUDIO) < 0) {
  993. -       plog_fmt("Couldn't initialize SDL: %s", SDL_GetError());
  994. +       plog_fmt("SDL: Couldn't initialize SDL: %s", SDL_GetError());
  995.         return false;
  996.     }
  997.  
  998.     /* Try to open the audio */
  999.     if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, 4096) < 0) {
  1000. -       plog_fmt("Couldn't open mixer: %s", SDL_GetError());
  1001. +       plog_fmt("SDL: Couldn't open mixer: %s", SDL_GetError());
  1002.         return false;
  1003.     }
  1004.  
  1005. @@ -120,228 +87,192 @@ static bool open_audio(void)
  1006.     return true;
  1007.  }
  1008.  
  1009. -
  1010. -
  1011.  /**
  1012. - * Read sound.cfg and map events to sounds; then load all the sounds into
  1013. - * memory to avoid I/O latency later.
  1014. + * Load a sound from file.
  1015.   */
  1016. -static bool sound_sdl_init(bool no_cache)
  1017. +static bool load_sample_sdl(sdl_sample *sample)
  1018.  {
  1019. -   char path[2048];
  1020. -   char buffer[2048];
  1021. -   ang_file *fff;
  1022. +   switch (sample->sample_type) {
  1023. +       case SDL_CHUNK:
  1024. +           sample->sample_data.chunk = Mix_LoadWAV(sample->path);
  1025.  
  1026. +           if (sample->sample_data.chunk)
  1027. +               return true;
  1028.  
  1029. -   /* Initialise the mixer  */
  1030. -   if (!open_audio())
  1031. -       return false;
  1032. +           break;
  1033.  
  1034. +       case SDL_MUSIC:
  1035. +           sample->sample_data.music = Mix_LoadMUS(sample->path);
  1036.  
  1037. -   /* Find and open the config file */
  1038. -   path_build(path, sizeof(path), ANGBAND_DIR_SOUNDS, "sound.cfg");
  1039. -   fff = file_open(path, MODE_READ, -1);
  1040. +           if (sample->sample_data.music)
  1041. +               return true;
  1042.  
  1043. -   /* Handle errors */
  1044. -   if (!fff) {
  1045. -       plog_fmt("Failed to open sound config (%s):\n    %s",
  1046. -                 path, strerror(errno));
  1047. -       return false;
  1048. +           break;
  1049. +
  1050. +       default:
  1051. +           plog_fmt("SDL: Oops - Unsupported file type");
  1052. +           break;
  1053.     }
  1054.  
  1055. -   /* Parse the file */
  1056. -   /* Lines are always of the form "name = sample [sample ...]" */
  1057. -   while (file_getl(fff, buffer, sizeof(buffer))) {
  1058. -       char *msg_name;
  1059. -       char *sample_list;
  1060. -       char *search;
  1061. -       char *cur_token;
  1062. -       char *next_token;
  1063. -       int event;
  1064. -
  1065. -       /* Skip anything not beginning with an alphabetic character */
  1066. -       if (!buffer[0] || !isalpha((unsigned char)buffer[0])) continue;
  1067. -
  1068. -       /* Split the line into two: message name, and the rest */
  1069. -       search = strchr(buffer, ' ');
  1070. -       sample_list = strchr(search + 1, ' ');
  1071. -       if (!search) continue;
  1072. -       if (!sample_list) continue;
  1073. -
  1074. -       /* Set the message name, and terminate at first space */
  1075. -       msg_name = buffer;
  1076. -       search[0] = '\0';
  1077. -
  1078. -
  1079. -       /* Make sure this is a valid event name */
  1080. -       event = message_lookup_by_sound_name(msg_name);
  1081. -       if (event < 0) continue;
  1082. -
  1083. -       /* Advance the sample list pointer so it's at the beginning of text */
  1084. -       sample_list++;
  1085. -       if (!sample_list[0]) continue;
  1086. -
  1087. -       /* Terminate the current token */
  1088. -       cur_token = sample_list;
  1089. -       search = strchr(cur_token, ' ');
  1090. -       if (search) {
  1091. -           search[0] = '\0';
  1092. -           next_token = search + 1;
  1093. -       } else {
  1094. -           next_token = NULL;
  1095. -       }
  1096. +   return false;
  1097. +}
  1098.  
  1099. -        /*
  1100. -         * Now we find all the sample names and add them one by one
  1101. -         */
  1102. -        while (cur_token) {
  1103. -           int num = samples[event].num;
  1104. -           bool got_file_type = false;
  1105. -
  1106. -           /* Don't allow too many samples */
  1107. -           if (num >= MAX_SAMPLES) break;
  1108. -
  1109. -           /* Build the path to the sample */
  1110. -           path_build(path, sizeof(path), ANGBAND_DIR_SOUNDS, cur_token);
  1111. -           if (!file_exists(path)) goto next_token;
  1112. -
  1113. -           if (!got_file_type) {
  1114. -                   if (streq(path + strlen(path) - 3, "mp3")) {
  1115. -                       use_mp3 = true;
  1116. -                   got_file_type = true;
  1117. -               }
  1118. -           }
  1119. +/**
  1120. + * Load a sound and return a pointer to the associated SDL Sound data
  1121. + * structure back to the core sound module.
  1122. + */
  1123. +static bool load_sound_sdl(const char *sound_name, void **data)
  1124. +{
  1125. +   char path[2048];
  1126. +   char *filename_buf;
  1127. +   size_t filename_buf_size;
  1128. +   sdl_sample *sample = NULL;
  1129. +   int i = 0;
  1130. +   bool loaded = false;
  1131. +
  1132. +   /* Build the path to the sample */
  1133. +   path_build(path, sizeof(path), ANGBAND_DIR_SOUNDS, sound_name);
  1134. +
  1135. +   /*
  1136. +    * Create a buffer to store the filename plus three character
  1137. +    * extension (5 = '.' + 3 character extension + '\0'
  1138. +    */
  1139. +   filename_buf_size = strlen(path) + 5;
  1140. +   filename_buf = mem_zalloc(filename_buf_size);
  1141. +
  1142. +   while ((SDL_NULL != supported_file_types[i].type) && (!loaded)) {
  1143. +       my_strcpy(filename_buf, path, filename_buf_size);
  1144. +       filename_buf = string_append(filename_buf,
  1145. +                        supported_file_types[i].extension);
  1146. +
  1147. +       if (file_exists(filename_buf)) {
  1148. +           if (!sample)
  1149. +               sample = mem_zalloc(sizeof(*sample));
  1150. +
  1151. +           if (sample) {
  1152. +               sample->sample_type = supported_file_types[i].type;
  1153. +               sample->path = string_make(filename_buf);
  1154. +
  1155. +               /* Try and load the sample file */
  1156. +               if (!load_sample_sdl(sample))
  1157. +                   mem_free(sample->path);
  1158. +               else
  1159. +                   loaded = true;
  1160.  
  1161. -           /* Don't load now if we're not caching */
  1162. -           if (no_cache) {
  1163. -               /* Just save the path for later */
  1164. -               samples[event].paths[num] = string_make(path);
  1165.             } else {
  1166. -               /* Load the file now */
  1167. -               if (use_mp3) {
  1168. -                   samples[event].mp3s[num] = Mix_LoadMUS(path);
  1169. -                   if (!samples[event].mp3s[num]) {
  1170. -                       plog_fmt("%s: %s", SDL_GetError(), strerror(errno));
  1171. -                       goto next_token;
  1172. -                   }
  1173. -               } else {
  1174. -                   samples[event].wavs[num] = Mix_LoadWAV(path);
  1175. -                   if (!samples[event].wavs[num]) {
  1176. -                           plog_fmt("%s: %s", SDL_GetError(), strerror(errno));
  1177. -                       goto next_token;
  1178. -                   }
  1179. -               }
  1180. -           }
  1181. -
  1182. -           /* Imcrement the sample count */
  1183. -           samples[event].num++;
  1184. -
  1185. -       next_token:
  1186. -
  1187. -           /* Figure out next token */
  1188. -           cur_token = next_token;
  1189. -           if (next_token) {
  1190. -               /* Try to find a space */
  1191. -               search = strchr(cur_token, ' ');
  1192. -
  1193. -               /* If we can find one, terminate, and set new "next" */
  1194. -               if (search) {
  1195. -                   search[0] = '\0';
  1196. -                   next_token = search + 1;
  1197. -               } else {
  1198. -                   /* Otherwise prevent infinite looping */
  1199. -                   next_token = NULL;
  1200. -               }
  1201. +               /* Out of memory */
  1202. +               mem_free(filename_buf);
  1203. +               data = NULL;
  1204. +               return false;
  1205.             }
  1206.         }
  1207. +
  1208. +       i++;
  1209.     }
  1210.  
  1211. -   /* Close the file */
  1212. -   file_close(fff);
  1213. +   mem_free(filename_buf);
  1214.  
  1215. +   if (!loaded) {
  1216. +       plog_fmt("SDL: Failed to load sound '%s')", sound_name);
  1217. +       mem_free(sample);
  1218. +       sample = NULL;
  1219. +   }
  1220.  
  1221. -   /* Success */
  1222. -   return true;
  1223. +   *data = (void *)sample;
  1224. +
  1225. +   return (NULL != sample);
  1226.  }
  1227.  
  1228.  /**
  1229. - * Play a sound of type "event".
  1230. + * Play the sound stored in the provided SDL Sound data structure.
  1231.   */
  1232. -static void play_sound(game_event_type type, game_event_data *data, void *user)
  1233. +static bool play_sound_sdl(void *data)
  1234.  {
  1235. -   Mix_Chunk *wave = NULL;
  1236. -   Mix_Music *mp3 = NULL;
  1237. -   int s;
  1238. -
  1239. -   int event = data->message.type;
  1240. -
  1241. -   /* Paranoia */
  1242. -   if (event < 0 || event >= MSG_MAX) return;
  1243. -
  1244. -   /* Check there are samples for this event */
  1245. -   if (!samples[event].num) return;
  1246. -
  1247. -   /* Choose a random event */
  1248. -   s = randint0(samples[event].num);
  1249. -   if (use_mp3)
  1250. -           mp3 = samples[event].mp3s[s];
  1251. -   else
  1252. -           wave = samples[event].wavs[s];
  1253. -
  1254. -   /* Try loading it, if it's not cached */
  1255. -   if (!(wave || mp3)) {
  1256. -       /* Verify it exists */
  1257. -       const char *filename = samples[event].paths[s];
  1258. -       if (!file_exists(filename)) return;
  1259. -
  1260. -       /* Load */
  1261. -       if (use_mp3)
  1262. -               mp3 = Mix_LoadMUS(filename);
  1263. -       else
  1264. -               wave = Mix_LoadWAV(filename);
  1265. -   }
  1266. -
  1267. -   /* Check to see if we have a sound again */
  1268. -   if (!(wave || mp3)) {
  1269. -       plog("SDL sound load failed.");
  1270. -       return;
  1271. +   sdl_sample *sample = (sdl_sample *)data;
  1272. +
  1273. +   if (sample) {
  1274. +       switch (sample->sample_type) {
  1275. +           case SDL_CHUNK:
  1276. +               if (sample->sample_data.chunk)
  1277. +                   return (0 == Mix_PlayChannel(-1, sample->sample_data.chunk, 0));
  1278. +               break;
  1279. +
  1280. +           case SDL_MUSIC:
  1281. +               if (sample->sample_data.music)
  1282. +                   return (0 == Mix_PlayMusic(sample->sample_data.music, 1));
  1283. +               break;
  1284. +
  1285. +           default:
  1286. +               break;
  1287. +       }
  1288.     }
  1289.  
  1290. -   /* Actually play the thing */
  1291. -   if (use_mp3)
  1292. -           Mix_PlayMusic(mp3, 1);
  1293. -   else
  1294. -           Mix_PlayChannel(-1, wave, 0);
  1295. +   return false;
  1296.  }
  1297.  
  1298. -
  1299.  /**
  1300. - * Init the SDL sound "module".
  1301. + * Free resources referenced in the provided SDL Sound data structure.
  1302.   */
  1303. -errr init_sound_sdl(int argc, char **argv)
  1304. +static bool unload_sound_sdl(void *data)
  1305.  {
  1306. -   int i;
  1307. -
  1308. -   /* Parse args */
  1309. -   for (i = 1; i < argc; i++) {
  1310. -       if (prefix(argv[i], "-c")) {
  1311. -           no_cache_audio = true;
  1312. -           plog("Audio cache disabled.");
  1313. -           continue;
  1314. +   sdl_sample *sample = (sdl_sample *)data;
  1315. +
  1316. +   if (sample) {
  1317. +       switch (sample->sample_type) {
  1318. +           case SDL_CHUNK:
  1319. +               if (sample->sample_data.chunk)
  1320. +                    Mix_FreeChunk(sample->sample_data.chunk);
  1321. +
  1322. +               break;
  1323. +
  1324. +           case SDL_MUSIC:
  1325. +               if (sample->sample_data.music)
  1326. +                   Mix_FreeMusic(sample->sample_data.music);
  1327. +
  1328. +               break;
  1329. +
  1330. +           default:
  1331. +               break;
  1332.         }
  1333. -   }
  1334.  
  1335. -   /* Load sound preferences if requested */
  1336. -   if (!sound_sdl_init(no_cache_audio)) {
  1337. -       plog("Failed to load sound config");
  1338. +       if (sample->path)
  1339. +           mem_free(sample->path);
  1340.  
  1341. -       /* Failure */
  1342. -       return (1);
  1343. +       mem_free(sample);
  1344.     }
  1345.  
  1346. -   /* Enable sound */
  1347. -   event_add_handler(EVENT_SOUND, play_sound, NULL);
  1348. -   atexit(close_audio);
  1349. +   return true;
  1350. +}
  1351. +
  1352. +/**
  1353. + * Shut down the SDL sound module and free resources.
  1354. + */
  1355. +static bool close_audio_sdl(void)
  1356. +{
  1357. +   /*
  1358. +    * Close the audio.
  1359. +    *
  1360. +    * NOTE: All samples will have been free'd by the sound subsystem
  1361. +    * calling unload_sound_sdl() for every sample that was loaded.
  1362. +    */
  1363. +   Mix_CloseAudio();
  1364. +
  1365. +   /* XXX This may conflict with the SDL port */
  1366. +   SDL_Quit();
  1367. +
  1368. +   return true;
  1369. +}
  1370. +
  1371. +/**
  1372. + * Init the SDL sound module.
  1373. + */
  1374. +errr init_sound_sdl(struct sound_hooks *hooks, int argc, char **argv)
  1375. +{
  1376. +   hooks->open_audio_hook = open_audio_sdl;
  1377. +   hooks->close_audio_hook = close_audio_sdl;
  1378. +   hooks->load_sound_hook = load_sound_sdl;
  1379. +   hooks->unload_sound_hook = unload_sound_sdl;
  1380. +   hooks->play_sound_hook = play_sound_sdl;
  1381.  
  1382.     /* Success */
  1383.     return (0);
  1384. diff --git a/src/snd-sdl.h b/src/snd-sdl.h
  1385. new file mode 100644
  1386. index 0000000..3700cea
  1387. --- /dev/null
  1388. +++ b/src/snd-sdl.h
  1389. @@ -0,0 +1,23 @@
  1390. +/**
  1391. + * \file sound.h
  1392. + * \brief Sound handling
  1393. + *
  1394. + * Copyright (c) 2016 Graeme Russ
  1395. + *
  1396. + * Redistribution and use in source and binary forms, with or without
  1397. + * modification, are permitted provided that the following conditions are met:
  1398. + *
  1399. + *  * Redistributions of source code must retain the above copyright notice,
  1400. + *    this list of conditions and the following disclaimer.
  1401. + *
  1402. + *  * Redistributions in binary form must reproduce the above copyright notice,
  1403. + *    this list of conditions and the following disclaimer in the documentation
  1404. + *    and/or other materials provided with the distribution.
  1405. + */
  1406. +
  1407. +#ifndef INCLUDED_Z_SOUND_SDL_H
  1408. +#define INCLUDED_Z_SOUND_SDL_H
  1409. +
  1410. +errr init_sound_sdl(struct sound_hooks *hooks, int argc, char **argv);
  1411. +
  1412. +#endif /* !INCLUDED_Z_SOUND_H */
  1413. diff --git a/src/sound-core.c b/src/sound-core.c
  1414. new file mode 100644
  1415. index 0000000..fc6210c
  1416. --- /dev/null
  1417. +++ b/src/sound-core.c
  1418. @@ -0,0 +1,410 @@
  1419. +/**
  1420. + * \file sound-core.c
  1421. + * \brief core sound support
  1422. + *
  1423. + * Copyright (c) 2016 Graeme Russ <graeme.russ@gmail.com>
  1424. + *
  1425. + * This work is free software; you can redistribute it and/or modify it
  1426. + * under the terms of either:
  1427. + *
  1428. + * a) the GNU General Public License as published by the Free Software
  1429. + *    Foundation, version 2, or
  1430. + *
  1431. + * b) the "Angband licence":
  1432. + *    This software may be copied and distributed for educational, research,
  1433. + *    and not for profit purposes provided that this copyright and statement
  1434. + *    are included in all such copies.  Other copyrights may also apply.
  1435. + */
  1436. +#include "angband.h"
  1437. +#include "init.h"
  1438. +#include "sound.h"
  1439. +#include "avltree.h"
  1440. +#include "main.h"
  1441. +
  1442. +#ifdef SOUND_SDL
  1443. +#include "snd-sdl.h"
  1444. +#endif
  1445. +
  1446. +struct sound_module
  1447. +{
  1448. +   const char *name;
  1449. +   const char *help;
  1450. +   errr (*init)(struct sound_hooks *hooks, int argc, char **argv);
  1451. +};
  1452. +
  1453. +/**
  1454. + * List of sound modules in the order they should be tried.
  1455. + */
  1456. +static const struct sound_module sound_modules[] =
  1457. +{
  1458. +#ifdef SOUND_SDL
  1459. +   { "sdl", "SDL_mixer sound module", init_sound_sdl },
  1460. +#endif /* SOUND_SDL */
  1461. +
  1462. +   { "", "", NULL },
  1463. +};
  1464. +
  1465. +/*
  1466. + * Two trees are needed:
  1467. + * - A mapping of 'sound names' to 'sound ids' - this is used during the
  1468. + *   initial parsing of the sound configuration file to ensure we don't
  1469. + *   load the same sounds multiple times (if a sound is mapped to more than
  1470. + *   one message). When the sound sub-system is initialised, this tree is
  1471. + *   'walked', with the sound name stored in each node passed to the platform
  1472. + *   sound module which loads the sound
  1473. + * - A mapping of 'message ids' to 'sound ids' - In the past, a static array
  1474. + *   of size [MAX_MESSAGES][MAX_SOUND_PER_MESSAGE] was used, which results
  1475. + *   in a horrendous waste of memory
  1476. + */
  1477. +
  1478. +/*****************************************************************************
  1479. + * Structures to map sound names to ids
  1480. + *****************************************************************************/
  1481. +typedef struct _sound_node sound_node;
  1482. +
  1483. +struct _sound_node
  1484. +{
  1485. +   char *sound_name;
  1486. +   u16b sound_id;
  1487. +
  1488. +   TREE_ENTRY(_sound_node) sound_tree;
  1489. +};
  1490. +
  1491. +static sound_node *sound_node_new(char *sound_name, u16b sound_id)
  1492. +{
  1493. +   sound_node *self = mem_zalloc(sizeof *self);
  1494. +
  1495. +   self->sound_name = string_make(sound_name);
  1496. +   self->sound_id = sound_id;
  1497. +   return self;
  1498. +}
  1499. +
  1500. +static int sound_node_compare(sound_node *lhs, sound_node *rhs)
  1501. +{
  1502. +   return (int)strcmp(lhs->sound_name, rhs->sound_name);
  1503. +}
  1504. +
  1505. +typedef TREE_HEAD(_sound_tree, _sound_node) tree_sound;
  1506. +
  1507. +TREE_DEFINE(_sound_node, sound_tree)
  1508. +
  1509. +static tree_sound sounds = TREE_INITIALIZER(sound_node_compare);
  1510. +/*****************************************************************************/
  1511. +
  1512. +/*****************************************************************************
  1513. + * Structures to map message ids to sound ids
  1514. + *****************************************************************************/
  1515. +typedef struct _msg_sound msg_sound;
  1516. +
  1517. +struct _msg_sound
  1518. +{
  1519. +   int sound_id;
  1520. +   msg_sound *next;
  1521. +};
  1522. +
  1523. +typedef struct _message_node message_node;
  1524. +
  1525. +struct _message_node
  1526. +{
  1527. +   u16b message_id;
  1528. +   int num_sounds;
  1529. +   msg_sound *first;
  1530. +
  1531. +   TREE_ENTRY(_message_node) message_tree;
  1532. +};
  1533. +
  1534. +static message_node *message_node_new(u16b message_id)
  1535. +{
  1536. +   message_node *self = mem_zalloc(sizeof *self);
  1537. +
  1538. +   self->message_id = message_id;
  1539. +
  1540. +   return self;
  1541. +}
  1542. +
  1543. +static int message_node_compare(message_node *lhs, message_node *rhs)
  1544. +{
  1545. +   return (rhs->message_id - lhs->message_id);
  1546. +}
  1547. +
  1548. +typedef TREE_HEAD(_message_tree, _message_node) tree_message;
  1549. +
  1550. +TREE_DEFINE(_message_node, message_tree)
  1551. +
  1552. +static tree_message messages = TREE_INITIALIZER(message_node_compare);
  1553. +/*****************************************************************************/
  1554. +
  1555. +/*
  1556. + * After processing the preference files, the 'sounds' AVL Tree will contain
  1557. + * next_sound_id nodes - each representing a sound that needs to be loaded.
  1558. + * We create the sound_data array once we know this information, and then
  1559. + * populate it by calling load_sound_hook() for each node in the tree
  1560. + */
  1561. +static u16b next_sound_id;
  1562. +static void **sound_data;
  1563. +
  1564. +/* These are the hooks installed by the platform sound module */
  1565. +static struct sound_hooks hooks;
  1566. +
  1567. +/**
  1568. + * Parse a string of sound names provided by the preferences parser and:
  1569. + *  - Add any new sounds to the 'sound names' tree and allocate them
  1570. + *    unique 'sound ids'
  1571. + *  - Add each sound assigned to a message type to that message types
  1572. + *    'sound map
  1573. + */
  1574. +void message_sound_define(u16b message_id, const char *sounds_str)
  1575. +{
  1576. +   char *search;
  1577. +   char *str;
  1578. +   char *cur_token;
  1579. +   char *next_token;
  1580. +
  1581. +   sound_node sound_search_node;
  1582. +   sound_node *existing_sound;
  1583. +   sound_node *new_sound;
  1584. +   u16b sound_id;
  1585. +
  1586. +   message_node message_search_node;
  1587. +   message_node *message_map;
  1588. +   msg_sound *new_message_sound;
  1589. +
  1590. +   /* sounds_str is a space separated list of sound names */
  1591. +   str = cur_token = string_make(sounds_str);
  1592. +
  1593. +   search = strchr(cur_token, ' ');
  1594. +
  1595. +   if (search) {
  1596. +       search[0] = '\0';
  1597. +       next_token = search + 1;
  1598. +   } else {
  1599. +       next_token = NULL;
  1600. +   }
  1601. +
  1602. +   if (cur_token) {
  1603. +       /* Do we already have a message->sounds mapping for this message ID? */
  1604. +       message_search_node.message_id = message_id;
  1605. +
  1606. +       message_map = TREE_FIND(&messages, _message_node, message_tree, &message_search_node);
  1607. +
  1608. +       if (!message_map) {
  1609. +           /* No - create one */
  1610. +           message_map = message_node_new(message_id);
  1611. +           TREE_INSERT(&messages, _message_node, message_tree, message_map);
  1612. +       }
  1613. +   }
  1614. +
  1615. +   /* Find all the sample names and add them one by one */
  1616. +   while (cur_token) {
  1617. +       /* Have we already processed this sound name? */
  1618. +       sound_search_node.sound_name = cur_token;
  1619. +
  1620. +       existing_sound = TREE_FIND(&sounds, _sound_node, sound_tree, &sound_search_node);
  1621. +
  1622. +       if (existing_sound) {
  1623. +           /* Yep - Just need to get the ID */
  1624. +           sound_id = existing_sound->sound_id;
  1625. +       } else {
  1626. +           /* Nope - Create a new node to store this sound's ID */
  1627. +           sound_id = next_sound_id;
  1628. +           new_sound = sound_node_new(cur_token, sound_id);
  1629. +           TREE_INSERT(&sounds, _sound_node, sound_tree, new_sound);
  1630. +
  1631. +           next_sound_id++;
  1632. +       }
  1633. +
  1634. +       /* Add this sound (by id) to the message->sounds map */
  1635. +       new_message_sound = mem_zalloc(sizeof *new_message_sound);
  1636. +       new_message_sound->sound_id = sound_id;
  1637. +       new_message_sound->next = message_map->first;
  1638. +       message_map->first = new_message_sound;
  1639. +       message_map->num_sounds++;
  1640. +
  1641. +       /* Figure out next token */
  1642. +       cur_token = next_token;
  1643. +
  1644. +       if (next_token) {
  1645. +           /* Try to find a space */
  1646. +           search = strchr(cur_token, ' ');
  1647. +
  1648. +           /* If we can find one, terminate, and set new "next" */
  1649. +           if (search) {
  1650. +               search[0] = '\0';
  1651. +               next_token = search + 1;
  1652. +           } else {
  1653. +               /* Otherwise prevent infinite looping */
  1654. +               next_token = NULL;
  1655. +           }
  1656. +       }
  1657. +   }
  1658. +
  1659. +   string_free(str);
  1660. +}
  1661. +
  1662. +/**
  1663. + * Play a sound of type "event".
  1664. + */
  1665. +static void play_sound(game_event_type type, game_event_data *data, void *user)
  1666. +{
  1667. +   int s, i, sound_id;
  1668. +   message_node message_search_node;
  1669. +   message_node *message_map;
  1670. +   msg_sound *message_sound;
  1671. +
  1672. +   int event = data->message.type;
  1673. +
  1674. +   /* Paranoia */
  1675. +   assert(event >= 0);
  1676. +
  1677. +   message_search_node.message_id = (u16b)event;
  1678. +
  1679. +   message_map = TREE_FIND(&messages, _message_node, message_tree, &message_search_node);
  1680. +
  1681. +   if (!message_map)
  1682. +       return; /* No sounds for this message */
  1683. +
  1684. +   /* Choose a random event */
  1685. +   message_sound = message_map->first;
  1686. +
  1687. +   if (!message_sound)
  1688. +       return; /* Oops */
  1689. +
  1690. +   s = randint0(message_map->num_sounds);
  1691. +
  1692. +   /*
  1693. +    * Walk the list - possibly inefficient if you define LOTS of sounds
  1694. +    * for LOTS of messages. Not worth using a more 'efficient' data
  1695. +    * structure
  1696. +    */
  1697. +   for (i = 0; i < s; i++)
  1698. +       if (message_sound->next)
  1699. +           message_sound = message_sound->next;
  1700. +
  1701. +   sound_id = message_sound->sound_id;
  1702. +
  1703. +   assert((sound_id >= 0) && (sound_id < next_sound_id));
  1704. +
  1705. +   hooks.play_sound_hook(sound_data[sound_id]);
  1706. +}
  1707. +
  1708. +/**
  1709. + * Call the platform sound modules 'load sound' function
  1710. + */
  1711. +static void load_sound(sound_node *self, void *ignore)
  1712. +{
  1713. +   void *plat_data;
  1714. +
  1715. +   if (hooks.load_sound_hook) {
  1716. +       if(!hooks.load_sound_hook(self->sound_name, &plat_data))
  1717. +           plog_fmt("Failed to load sound: %s", self->sound_name);
  1718. +       else
  1719. +           sound_data[self->sound_id] = plat_data;
  1720. +   }
  1721. +}
  1722. +
  1723. +/*
  1724. + * Recursive function to delete sound id's from a node in the 'messages' tree
  1725. + */
  1726. +void delete_message_sound(msg_sound *sound)
  1727. +{
  1728. +   assert(sound);
  1729. +
  1730. +   if (sound->next)
  1731. +       delete_message_sound(sound->next);
  1732. +
  1733. +   mem_free(sound);
  1734. +}
  1735. +/*
  1736. + * Shut down the sound system and free resources.
  1737. + */
  1738. +static void close_audio(void)
  1739. +{
  1740. +   int i;
  1741. +
  1742. +   if (0 == next_sound_id)
  1743. +       return; /* Never opened */
  1744. +
  1745. +   /*
  1746. +    * Ask the platforms sound module to free resources for each
  1747. +    * sound
  1748. +    */
  1749. +   if (hooks.unload_sound_hook)
  1750. +       for (i = 0; i < next_sound_id; i++)
  1751. +           hooks.unload_sound_hook(sound_data[i]);
  1752. +
  1753. +   mem_free(sound_data);
  1754. +
  1755. +   /* Delete the 'sound names' tree */
  1756. +   while (sounds.th_root) {
  1757. +       mem_free(sounds.th_root->sound_name);
  1758. +       TREE_REMOVE(&sounds, _sound_node, sound_tree, sounds.th_root);
  1759. +   }
  1760. +
  1761. +   /* Delete the 'message map' tree */
  1762. +   while (messages.th_root) {
  1763. +       delete_message_sound(messages.th_root->first);
  1764. +       TREE_REMOVE(&messages, _message_node, message_tree, messages.th_root);
  1765. +   }
  1766. +
  1767. +   /* Close the platform's sound module */
  1768. +   if (hooks.close_audio_hook)
  1769. +       hooks.close_audio_hook();
  1770. +}
  1771. +
  1772. +
  1773. +/**
  1774. + * Init the sound "module".
  1775. + */
  1776. +errr init_sound(const char *soundstr, int argc, char **argv)
  1777. +{
  1778. +   int i = 0;
  1779. +   bool done = false;
  1780. +
  1781. +   /* Only initialise the sound sub-system if we have sounds to play */
  1782. +   if (0 == next_sound_id)
  1783. +       return 0;   /* It's not a fail if no sounds defined */
  1784. +
  1785. +   /* Try the modules in the order specified by sound_modules[] */
  1786. +   while (sound_modules[i].init && !done) {
  1787. +       if (!soundstr || streq(soundstr, sound_modules[i].name))
  1788. +           if (0 == sound_modules[i].init(&hooks, argc, argv))
  1789. +               done = true;
  1790. +       i++;
  1791. +   }
  1792. +
  1793. +   /* Check that we have a sound module to use */
  1794. +   if (!done)
  1795. +       return 1;
  1796. +
  1797. +   /* Open the platform specific sound system */
  1798. +   if (!hooks.open_audio_hook)
  1799. +       return 1;
  1800. +
  1801. +   if (!hooks.open_audio_hook(argc, argv))
  1802. +       return 1;
  1803. +
  1804. +   /* Allocate the array which stores the platform specific sound data */
  1805. +   sound_data = mem_zalloc(sizeof(void *) * next_sound_id);
  1806. +
  1807. +   /* Walk the 'sound names' tree, calling load_sound() for each node */
  1808. +   TREE_FORWARD_APPLY(&sounds, _sound_node, sound_tree, load_sound, NULL);
  1809. +
  1810. +   /* Enable sound */
  1811. +   event_add_handler(EVENT_SOUND, play_sound, NULL);
  1812. +   atexit(close_audio);
  1813. +
  1814. +   /* Success */
  1815. +   return (0);
  1816. +}
  1817. +
  1818. +/**
  1819. + * Print out the 'help' information for the sound module.
  1820. + */
  1821. +void print_sound_help(void)
  1822. +{
  1823. +   int i;
  1824. +
  1825. +   for (i = 0; i < (int)N_ELEMENTS(sound_modules); i++)
  1826. +       printf("     %s   %s\n", sound_modules[i].name,
  1827. +              sound_modules[i].help);
  1828. +}
  1829. diff --git a/src/sound.h b/src/sound.h
  1830. new file mode 100644
  1831. index 0000000..cb49f0d
  1832. --- /dev/null
  1833. +++ b/src/sound.h
  1834. @@ -0,0 +1,38 @@
  1835. +/**
  1836. + * \file sound.h
  1837. + * \brief Sound handling
  1838. + *
  1839. + * Copyright (c) 2016 Graeme Russ
  1840. + *
  1841. + * Redistribution and use in source and binary forms, with or without
  1842. + * modification, are permitted provided that the following conditions are met:
  1843. + *
  1844. + *  * Redistributions of source code must retain the above copyright notice,
  1845. + *    this list of conditions and the following disclaimer.
  1846. + *
  1847. + *  * Redistributions in binary form must reproduce the above copyright notice,
  1848. + *    this list of conditions and the following disclaimer in the documentation
  1849. + *    and/or other materials provided with the distribution.
  1850. + */
  1851. +
  1852. +#ifndef INCLUDED_SOUND_H
  1853. +#define INCLUDED_SOUND_H
  1854. +
  1855. +struct sound_hooks
  1856. +{
  1857. +   bool (*open_audio_hook)(int argc, char **argv);
  1858. +   bool (*close_audio_hook)(void);
  1859. +
  1860. +   /* 'data' is a sound module specific struct */
  1861. +   bool (*load_sound_hook)(const char *sound_name, void **data);
  1862. +   bool (*unload_sound_hook)(void *data);
  1863. +   bool (*play_sound_hook)(void *data);
  1864. +};
  1865. +
  1866. +errr init_sound(const char *soundstr, int argc, char **argv);
  1867. +
  1868. +void message_sound_define(u16b type, const char *sounds);
  1869. +
  1870. +void print_sound_help(void);
  1871. +
  1872. +#endif /* !INCLUDED_SOUND_H */
  1873. diff --git a/src/ui-prefs.c b/src/ui-prefs.c
  1874. index cff07cf..e32ba72 100644
  1875. --- a/src/ui-prefs.c
  1876. +++ b/src/ui-prefs.c
  1877. @@ -34,6 +34,7 @@
  1878.  #include "ui-keymap.h"
  1879.  #include "ui-prefs.h"
  1880.  #include "ui-term.h"
  1881. +#include "sound.h"
  1882.  
  1883.  int arg_graphics;          /* Command arg -- Request graphics mode */
  1884.  bool arg_graphics_nice;        /* Command arg -- Request nice graphics mode */
  1885. @@ -1047,6 +1048,29 @@ static enum parser_error parse_prefs_window(struct parser *p)
  1886.     return PARSE_ERROR_NONE;
  1887.  }
  1888.  
  1889. +static enum parser_error parse_prefs_sound(struct parser *p)
  1890. +{
  1891. +   int msg_index;
  1892. +   const char *type;
  1893. +   const char *sounds;
  1894. +
  1895. +   struct prefs_data *d = parser_priv(p);
  1896. +   assert(d != NULL);
  1897. +   if (d->bypass) return PARSE_ERROR_NONE;
  1898. +
  1899. +   type = parser_getsym(p, "type");
  1900. +   sounds = parser_getstr(p, "sounds");
  1901. +
  1902. +   msg_index = message_lookup_by_name(type);
  1903. +
  1904. +   if (msg_index < 0)
  1905. +       return PARSE_ERROR_INVALID_MESSAGE;
  1906. +
  1907. +   message_sound_define(msg_index, sounds);
  1908. +
  1909. +   return PARSE_ERROR_NONE;
  1910. +}
  1911. +
  1912.  static struct parser *init_parse_prefs(bool user)
  1913.  {
  1914.     struct parser *p = parser_new();
  1915. @@ -1074,6 +1098,7 @@ static struct parser *init_parse_prefs(bool user)
  1916.     parser_reg(p, "message sym type sym attr", parse_prefs_message);
  1917.     parser_reg(p, "color uint idx int k int r int g int b", parse_prefs_color);
  1918.     parser_reg(p, "window int window uint flag uint value", parse_prefs_window);
  1919. +   parser_reg(p, "sound sym type str sounds", parse_prefs_sound);
  1920.  
  1921.     return p;
  1922.  }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top