I was having many issues with thread synchronization (especially deadlocks)
so I decided to redesign everything in a cleaner way.

thread 1: main thread
thread 2: ??? something about xlib? we don't care
thread 3: timer thread (scrolling, ...)
thread 4: signal thread
thread n-th: player threads (decoder thread and scan thread with
  player_mad). Here runs my_callback too.

To avoid deadlock problems, mutexes are to be locked in order of priority.
For example, if I've locked mtx 3 I cannot lock mtx 2 before unlocking 3.
I can (re)lock 3 *after* locking 2, and so on.
Mutexes are listed in order of priority (high priority first).
N.B. 1 is higher priority then 2.

N.B. JOINING A THREAD MUST BE DONE WITHOUT HOLDING ANY MUTEX THE JOINED
THREAD MIGHT HOLD, DEADLOCK DANGER!!!


SHARED VARIABLES

main.c:

  terminate: main(rw), signal(wo) ==> atomic access, no problems

player.c:

  + some parts needs to wait for my_callback to terminate
  \- callback_mtx

  + X display: main, timer, callback
  \- XLockDisplay/XUnlockDisplay

  + lists, alloc_lists, num_list: main(rw), callback(rw)
  \- list_mtx

  + curr_list, curr_song, num_songs: main(rw), callback(rw)
  + rand_song_num: main(rw), callback(rw)
  \- song_num_mtx

  + song_length: main(rw), callback(rw)
  + title: main(rw), scrolling(ro), callback(rw)
  + song hash: main(rw), callback(rw)
  \- song_mtx

  + scroll_pos, do_scroll: main(rw), scrolling(rw), callback(rw)
  \- scroll_mtx

  + curr_player: main(rw), callback(rw) ==> it should worry itself about
  |   concurrency and mutual exclusion problems for its methods.
  |   Only need to worry about the phisical memory area.
  \- player_mtx

  --- from here down only harmless shared variables ---
  player_tab: main(wo on load, else ro), callback(ro) ==> no sync problems
  mpg123_argv: main (wo, on load), mpg123 player (ro) ==> no sync problems
  file_ext, list_ext: main(ro, wo on load), callback(ro) ==> no sync problems
  always_scroll: main(wo on load), scrolling(ro) ==> no problems
  show_time_remain: main(wo), callback(ro) ==> atomic access, no problems
  repeat_flag, random_flag: main(rw), callback(rw) ==> atomic access,
    no real problems here
  show_listname: main(wo), callback(rw) ==> I think there's no need to worry
  is_scolling: main, timer ==> no need to worry, atomic access

player_mad.c:
  --- MUTEXES NOT DEFINED YET, BUT THEY'RE LOWER PRIORITY ---

  player threads are:
  scan thread (pre-scan of mp3 file to gather all infos)
  decoder thread (the actual player)

  variables in player_mad struct:
  pl.status: main(rw), decoder(rw)
  pos: main(get_pos, ro), decoder(rw)
  len: main(get_length, ro), decoder(ro), scan(wo) ==> just be sure ther're
    available when read by main or decoder thread
  callback, cb_param: main(wo), decoder(ro), scan(ro)
  filename: main(rw), decoder(rw), scan(ro)

  + infd, mtime, flen: main(rw), decoder(ro)
  + mmap, buffer: main(rw), decoder(ro), scan(ro)
  \- infile_mtx

  + title: main(rw), scan(wo)
  \- title_mtx 

  eof: main(rw), decoder(rw)

  + dec_msg_cond: main, decoder
  + dec_msg_tx, dec_msg_rx: decoder(ro), main(wo)
  + dec_seek: decoder(ro), main(wo)
  \- dec_msg_mtx

  --- these are ok by themselves (i hope at least :) ---
  scan_thr: main(rw), decoder(rw)
  scan_thr_running: scan(wo), decoder(ro), main(ro)
  dec_thr: main(rw), decoder(rw)
  dec_thr_running: scan(wo), decoder(ro), main(ro)
  --- these cause no harm ---
  abort_scan: main(wo), decoder(wo), scan(ro) ==> no problems
