في سطح المكتب كتبت هذا البرنامج متوافقاً مع i3block لطباعة معلومات مقطع الصوت الذي يعمل حالياً على MPD أو مع غيره من المشغلات الصوتية / المرئية.

المشغلات المدعومة:

  • مشغلات MPD أو المتوافق معها كـMopidy.
  • VLC, SMPlayer, audacious, bmp, xmms2 باستخدام playerctl.
  • YouTube صوتي باستخدام mps-youtube و playerctl.
  • YouTube باستخدام SMTube و playerctl.
  • مشغل Spotify باستخدام playerctl ولكن الحساب المجاني لا يدعم الانتقال خلال الملف الصوتي تقديماً وتأخيراً.

الميزات:

  • نمطي عرض، عادي، ومختصر عند امتلاء الشريط.
  • عرض زمن التشغيل، اسم الملف، اسم المغني، الألبوم، عام الإصدار.
  • تشغيل / إيقاف مؤقت بالضغط على الشريط بالزر الأيسر للفأرة.
  • عند التعرف على كلمات الأغنية، يعرض ذلك عند الضغط على الشريط بالزر الأيمن للفأرة.
  • استخدام دولاب الفأرة للتقدم / التراجع بزمن تشغيل الملف.

إعدادات الإضافة للشريط في ملف i3blocks config

[music]
command=$HOME/scripts/i3blocks/music
interval=1
label=
markup=pango

ثم تفعيل الشريط (مع تغيير الإعداد بما يناسب) في إعداد ~/.i3/config، لاحظ استدعاء خط FontAwesome الذي ينبغي أن يكون منصباً على الجهاز حتى يعرض الأيقونات.

bar {
  position top
  font pango:DejaVu Sans Mono 8, FontAwesome 8
  output $monitor_primary
  tray_output none
  workspace_buttons yes
  strip_workspace_numbers yes
  binding_mode_indicator yes
  status_command i3blocks -c $HOME/.config/i3blocks/config-top
}

إعدادات أزرار الوسائط في ملف الإعدادات ~/.i3/config

# زر التشغيل يشغل / يوقف آنياً
bindsym XF86AudioPlay exec "$HOME/scripts/i3blocks/music toggle"
# Ctrl+زر التشغيل يوقف المشغّل
bindsym Ctrl+XF86AudioPlay exec "$HOME/scripts/i3blocks/music stop"
# زر السابق يؤخر الملف الحالي لـ10 ثوان
bindsym XF86AudioPrev exec "$HOME/scripts/i3blocks/music seek-"
# Ctrl+زر السابق يشغل الملف السابق
bindsym Ctrl+XF86AudioPrev exec "$HOME/scripts/i3blocks/music prev"
# زر التالي يقدم الملف الحالي لـ10 ثوان
bindsym XF86AudioNext exec "$HOME/scripts/i3blocks/music seek+"
# Ctrl+زر الحالي يشغل الملف الحالي
bindsym Ctrl+XF86AudioNext exec "$HOME/scripts/i3blocks/music next"

البرنامج، محفوظاً حسب ما مرّ بإعداد ملف i3blocks config وله صلاحيات التشغيل

#!/bin/bash
MPD_PASSWORD=/dev/null
MPD_SERVER=localhost
MPC="mpc -h $MPD_PASSWORD@$MPD_SERVER"

convertsecs() {
  ((h=${1}/3600))
  ((m=(${1}%3600)/60))
  ((s=${1}%60))
  if [[ $h -gt 0 ]]; then
    printf "%02d:%02d:%02d\n" $h $m $s
  else
    printf "%02d:%02d\n" $m $s

  fi
}

function show_lyrics() {
  lyrics=`$HOME/scripts/lyrics "$title" "$artist"`

  if [[ ! $lyrics ]]; then
    return
  fi

  if [[ $1 == "notify" ]]; then
    notify-send "$lyrics"
  elif [[ $1 == "echo" ]]; then
    echo "$lyrics"
  fi
}

# الأولوية لـMPD قبل أي مشغّل
status=`$MPC status | grep -E '\[.+?\]' | awk '{print $1}'`
s_status=`playerctl status`
if [[ $status == '[playing]' ]]; then
  PLAYER=mpd
elif [[ $status == '[paused]' ]]; then
  if [[ $s_status == "Playing" ]]; then
    PLAYER=playerctl
  else
    PLAYER=mpd
  fi
elif [[ $s_status == "Playing" || $s_status == "Paused" ]]; then
  PLAYER=playerctl
else
  echo -n ""
fi

if [[ $PLAYER == mpd ]]; then
  if [[ $status == '[playing]' ]]; then
    status=elif [[ $status == '[paused]' ]]; then
    status=fi

  position=`$MPC -f %position% | sed -n 2p | awk '{print $3}'`

  text="$status ($position) "

  file_name=`$MPC -f %file% | head -n1`
  file_name=${file_name##*/}
  file_name=${file_name%.*}

  artist=`$MPC -f %artist% | head -n1`

  title=`$MPC -f %title% | head -n1`

  album=`$MPC -f %album% | head -n1`

  date=`$MPC -f %date% | head -n1`

  volume=`$MPC -f %position% | sed -n 3p | awk '{print $2}'`

  case $BLOCK_BUTTON in
    1 ) $MPC toggle;;
    3 ) show_lyrics "notify";;
    4 ) $MPC seek +10;;
    5 ) $MPC seek -10;;
  esac

elif [[ $PLAYER == playerctl ]]; then

  status=`playerctl status`

  if [[ $status == 'Playing' ]]; then
    status=elif [[ $status == 'Paused' ]]; then
    status=fi


  position=`playerctl metadata`
  regex="'(.{1,5}):length'"
  if [[ $position =~ $regex ]]; then
    position=`playerctl metadata ${BASH_REMATCH[1]}:length`
    position=${position%.*}
    position=$((position/1000000))
    position=`convertsecs $position`

  fi

  current_position=`playerctl position`
  current_position=$(echo "$current_position"|bc)
  current_position=${current_position%%.*}
  current_position=`convertsecs $current_position`

  text="$status ($current_position/$position) "

  artist=`playerctl metadata artist`

  title=`playerctl metadata title`

  album=`playerctl metadata album`

  date=`playerctl metadata xesam:contentCreated`
  volume=$(echo "`playerctl volume`*100"|bc)
  volume=${volume%%.*}%

  case $BLOCK_BUTTON in
    1 ) playerctl play-pause;;
    3 ) show_lyrics "notify";;
    4 ) playerctl position 10+;;
    5 ) playerctl position 10-;;
  esac
fi

if [[ $artist ]]; then
  text="$text <span foreground=\"#C0C000\">"`echo "$artist" | recode utf8..html`"</span>"
fi

if [[ $artist && $title ]]; then
  text="$text, <span foreground=\"#E54C62\">"`echo "$title " | recode utf8..html`"</span>"
elif [[ $title ]]; then
  text="$text <span foreground=\"#E54C62\">"`echo "$title " | recode utf8..html`"</span>"
fi

if [[ $album ]]; then
  text="$text  (<span foreground=\"#00E0E0\">"`echo "$album " | recode utf8..html`"</span>)"
fi

if [[ $date && $date != '0' ]]; then
  text="$text [<span foreground=\"#C0C0C0\">"`echo "$date " | recode utf8..html`"</span>]"
fi

if [[ !$artist && !$title && !$album && !$date ]]; then
  text="$text<span foreground=\"#E54C62\">"`echo "$file_name " | recode utf8..html`"</span>"
fi


if [[ $PLAYER == playerctl && `playerctl -l | head -n1` =~ "mps-youtube" ]]; then
  text="$text <span foreground=\"#cd201f\"></span>"
fi

if [[ $volume ]]; then
  if [[ ${volume%?} -le 5 ]]; then
    volume=" ${volume}"
  elif [[ ${volume%?} -le 50 ]]; then
    volume=" ${volume}"
  else
    volume=" ${volume}"
  fi

  text="$text | $volume"
fi

if [[ ${#title} -ge 20 ]]; then
  short_text=`echo -n $title | awk '{print substr($0,2,20)}'`
  short_text="($position) $status $short_text..."
fi

# إن لم يكن هناك أي ملف من أي مشغّل، حاول بدء المشغّل
function toggle() {
  if [[ $PLAYER == mpd || `playerctl status 2>&1` == "Connection to player failed: No players found" ]]; then
    $MPC toggle
  elif [[ $PLAYER == playerctl || `mpc 2>&1` == "mpd error: Connection refused" ]]; then
    playerctl play-pause
  fi
}

function stop() {
  if [[ $PLAYER == mpd ]]; then
    $MPC stop
  elif [[ $PLAYER == playerctl ]]; then
    playerctl stop
  fi
}

function seek() {
  if [[ $PLAYER == mpd ]]; then
    $MPC seek ${1}10
  elif [[ $PLAYER == playerctl ]]; then
    playerctl position 10${1}
  fi
}

function next() {
  if [[ $PLAYER == mpd ]]; then
    $MPC next
  elif [[ $PLAYER == playerctl ]]; then
    playerctl next
  fi
}

function prev() {
  if [[ $PLAYER == mpd ]]; then
    $MPC prev
  elif [[ $PLAYER == playerctl ]]; then
    playerctl previous
  fi
}

case $1 in
  toggle )
    toggle;;
  stop)
    stop;;
  seek-)
    seek "-";;
  seek+)
    seek "+";;
  next)
    next;;
  prev)
    prev;;
  lyrics)
    show_lyrics "echo";;
esac

echo $text
echo $short_text