From a4c0a67040447a2d4b3bee702084c8256d8ca56d Mon Sep 17 00:00:00 2001 From: ziro Date: Thu, 16 Jul 2020 10:16:44 +0700 Subject: [PATCH] + Added all my custom commands --- .local/bin/custom/cov | 64 +++ .local/bin/custom/dmenumount | 25 ++ .local/bin/custom/dmenuumount | 12 + .local/bin/custom/ff2mpv | 38 ++ .local/bin/custom/games | 41 ++ .local/bin/custom/img-compress | 5 + .local/bin/custom/mcpelauncher-dmenu | 7 + .local/bin/custom/mcpelauncher-rpc | 45 ++ .local/bin/custom/mpv-link | 4 + .local/bin/custom/netcheck | 3 + .local/bin/custom/play | 4 + .local/bin/custom/prepare_webcam | 624 +++++++++++++++++++++++++++ .local/bin/custom/twitch-dmenu | 6 + 13 files changed, 878 insertions(+) create mode 100755 .local/bin/custom/cov create mode 100755 .local/bin/custom/dmenumount create mode 100755 .local/bin/custom/dmenuumount create mode 100755 .local/bin/custom/ff2mpv create mode 100755 .local/bin/custom/games create mode 100755 .local/bin/custom/img-compress create mode 100755 .local/bin/custom/mcpelauncher-dmenu create mode 100755 .local/bin/custom/mcpelauncher-rpc create mode 100755 .local/bin/custom/mpv-link create mode 100755 .local/bin/custom/netcheck create mode 100755 .local/bin/custom/play create mode 100755 .local/bin/custom/prepare_webcam create mode 100755 .local/bin/custom/twitch-dmenu diff --git a/.local/bin/custom/cov b/.local/bin/custom/cov new file mode 100755 index 0000000..d47c630 --- /dev/null +++ b/.local/bin/custom/cov @@ -0,0 +1,64 @@ +#!/bin/bash + +file="cov.txt" +fileold="cov.txt.old" + +update() { + mv ~/.cache/cov.txt ~/.cache/cov.txt.old + curl -s https://covid19.go.id/ | grep -A1 "div>Positif" | cut -d">" -f4 | cut -d"<" -f1 | sed "1 s/^/Pos /;2 s/^/Sem /" > ~/.cache/cov.txt +} + +helpFunction() +{ + echo "" + echo "Usage: $0 [Option]" + echo -e "\t-u Force update covid report" + echo -e "\t-p Print postive cases of covid-19 (Indonesia)" + echo -e "\t-s Print cured cases of covid-19 (Indonesia)" + echo -e "\t-H Print covid report in human format" + echo -e "\t-h Show this message" + exit 1 # Exit script after printing help +} + +print_Pos() { + printf "%s\n" $(grep "Pos" ~/.cache/$file | sed "s/Pos //") +} + +print_Sem() { + printf "%s\n" $(grep "Sem" ~/.cache/$file | sed "s/Sem //") +} + +print_Hum() { + print_Pos | sed '1 s/^/Positive: /g' && print_Sem | sed '1 s/^/Cured: /g' && echo -e "\nSource: https://covid19.go.id/" +} + +rate_Pos() { + newPos=$(cov -p | sed 's/[.]//g') + oldPos=$(cov -op | sed 's/[.]//g') + ((ratePos=$newPos-$oldPos)) + printf "%s\n" $ratePos +} + +rate_Sem() { + newPos=$(cov -s | sed 's/[.]//g') + oldPos=$(cov -os | sed 's/[.]//g') + ((ratePos=$newPos-$oldPos)) + printf "%s\n" $ratePos +} + +[ ! "$(stat -c %y ~/.cache/cov.txt 2> /dev/null | cut -d' ' -f1)" = "$(date +"%Y-%m-%d")" ] && update + +while getopts "oupshHrR" opt +do + case "$opt" in + R ) rate_Sem ;; + r ) rate_Pos ;; + o ) file="$fileold";; + u ) update && echo "Covid report has been updated";; + p ) print_Pos ;; + s ) print_Sem ;; + H ) print_Hum ;; + h ) helpFunction ;; + ? ) helpFunction ;; # Print helpFunction in case parameter is non-existent + esac +done diff --git a/.local/bin/custom/dmenumount b/.local/bin/custom/dmenumount new file mode 100755 index 0000000..6a1d71a --- /dev/null +++ b/.local/bin/custom/dmenumount @@ -0,0 +1,25 @@ +#!/bin/sh + +#mountables=$(lsblk -nrpo "name,type,size,mountpoint" | awk '$1!~/sda/ && $2!~/disk/ {print $1" ("$3") "}') + +mountables=$(lsblk -nrpo "name,size,type,mountpoint" | awk '/part $/ {print $1" ("$2") "}') +[ -z "$mountables" ] && notify-send "There's no mountable drive." && exit 1 +chosen=$(echo "$mountables" | dmenu -i -p "Devices"| awk '{print $1}') +[ -z "$chosen" ] && exit 1 +sudo mount -o rw "$chosen" 2> /dev/null && exit 0 + +dir=$(find /mnt/ -maxdepth 1 -type d | awk '!/t\/$/ && !/mnt\/4/') +[ -z "$dir" ] && exit 1 +chosenDir=$(echo "$dir" | dmenu -i -p "Mountpoint") +[ -z "$chosenDir" ] && exit 1 +if [ ! -d "$chosenDir" ]; then + choice=$(echo -en "Yes\nNo" | dmenu -i -p "Create new dir?") + case $choice in + "Yes") mkdir $chosenDir ;; + "No") exit 1 ;; + esac + [ -z $choice ] && notify-send "Mounting Failed" "$chosenDir is not exist." && exit 1 +else + sudo mount -o rw "$chosen" "$chosenDir" + notify-send "Mounting..." "$chosen to $chosenDir" +fi diff --git a/.local/bin/custom/dmenuumount b/.local/bin/custom/dmenuumount new file mode 100755 index 0000000..ba8fec4 --- /dev/null +++ b/.local/bin/custom/dmenuumount @@ -0,0 +1,12 @@ +#!/bin/sh + +un_mountables=$(lsblk -nrpo "name,size,type,mountpoint" | awk '$1!~/sda/ && $3!~/disk/ && !/part $/ {print $1" ("$2") on "$4}') +[ -z "$un_mountables" ] && notify-send "There's no mounted drive." && exit 1 +chosen=$(echo "$un_mountables" | dmenu -i -p "Devices" | awk '{print $1}') +[ -z "$chosen" ] && exit 1 + +prompt=$(echo -en "Yes\nNo" | dmenu -i -p "Are you sure?") +case $prompt in + "Yes") sudo umount $chosen && notify-send "Unmounting..." "$chosen";; + "No") exit 1 ;; +esac diff --git a/.local/bin/custom/ff2mpv b/.local/bin/custom/ff2mpv new file mode 100755 index 0000000..67ba863 --- /dev/null +++ b/.local/bin/custom/ff2mpv @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 + +import sys +import struct +import json +from subprocess import Popen, DEVNULL + + +def main(): + message = get_message() + url = message.get("url") + args = ["mpv", "--no-terminal", "--", url] + Popen(args, stdin=DEVNULL, stdout=DEVNULL, stderr=DEVNULL) + # Need to respond something to avoid "Error: An unexpected error occurred" + # in Browser Console. + send_message("ok") + + +# https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Native_messaging#App_side +def get_message(): + raw_length = sys.stdin.buffer.read(4) + if not raw_length: + return {} + length = struct.unpack("@I", raw_length)[0] + message = sys.stdin.buffer.read(length).decode("utf-8") + return json.loads(message) + + +def send_message(message): + content = json.dumps(message).encode("utf-8") + length = struct.pack("@I", len(content)) + sys.stdout.buffer.write(length) + sys.stdout.buffer.write(content) + sys.stdout.buffer.flush() + + +if __name__ == "__main__": + main() diff --git a/.local/bin/custom/games b/.local/bin/custom/games new file mode 100755 index 0000000..da06b37 --- /dev/null +++ b/.local/bin/custom/games @@ -0,0 +1,41 @@ +#!/bin/sh +gamedir="$HOME/my Games/" +gametype= +gm="gamemoderun" +notify=1 +usage() { echo "Usage: dmenugames [-t GAMETYPE]" 1>&2; exit 1; } +while getopts t: name +do + case $name in + t) gametype="$2";; + ?) usage;; + esac +done +shift "$((OPTIND-1))" + +[ -z $gametype ] && usage; +games=$(find "$gamedir$gametype" -maxdepth 2 | sort | grep "$gametype/" | awk '!/.binary|.cue|.txt/' | sed 's/^.*s\///') +chosen="$gamedir$(echo -en "$games" | dmenu -i -l 10 -p "$gametype Games")" + [ "$chosen" = "$gamedir" ] && exit 1 + + [ "$chosen" = "$HOME/my Games/PC/Minecraft - Pocket Edition" ] && notify=0 + +[ $notify -eq 1 ] && notify-send "Launching..." "$chosen" + +if [ "$gametype" = "3DS" ]; then + $gm citra-qt "$chosen" & +elif [ "$gametype" = "NES" ]; then + $gm nestopia -f "$chosen" & +elif [ "$gametype" = "PS2" ]; then + $gm PCSX2 --nogui --fullscreen "$chosen" & +elif [ "$gametype" = "PC" ]; then + "$chosen" & +elif [ "$gametype" = "PS1" ]; then + $gm pcsxr -cdfile "$chosen" & +# elif [ "$gametype" = "PC" ]; then +# $gm "$chosen" & +else + notify-send "Failed" "$gametype is not supported yet." + exit 1 +fi + diff --git a/.local/bin/custom/img-compress b/.local/bin/custom/img-compress new file mode 100755 index 0000000..35da95e --- /dev/null +++ b/.local/bin/custom/img-compress @@ -0,0 +1,5 @@ +#!/bin/sh +case $1 in + *.jpg | *.jpeg ) jpegoptim $1 ;; + *.png ) optipng $1 ;; +esac diff --git a/.local/bin/custom/mcpelauncher-dmenu b/.local/bin/custom/mcpelauncher-dmenu new file mode 100755 index 0000000..12bff4a --- /dev/null +++ b/.local/bin/custom/mcpelauncher-dmenu @@ -0,0 +1,7 @@ +#!/bin/sh + +version=$(find ~/.local/share/mcpelauncher/versions -maxdepth 1 | sort -r | awk '!/ns$/ && !/.ini/' | sed "s/^.*s\///" | dmenu -l 10 -i -p "MCPE Versions") +[ -z $version ] && exit 1 + +gamemoderun mcpelauncher-client -dg ~/.local/share/mcpelauncher/versions/$version & +sleep 5s && mcpelauncher-rpc "$version" diff --git a/.local/bin/custom/mcpelauncher-rpc b/.local/bin/custom/mcpelauncher-rpc new file mode 100755 index 0000000..01f34f4 --- /dev/null +++ b/.local/bin/custom/mcpelauncher-rpc @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +import sys, getopt, pypresence, time, psutil + +# ----- RPC Client ID +RPC = pypresence.Presence("731745989039489036") + +# ----- Functions +def connect_rpc(): + while True: + try: + RPC.connect() + break + except ConnectionRefusedError as e: + print("Failed to connect to RPC! Trying again in 10 seconds...") + time.sleep(10) + except (FileNotFoundError, AttributeError) as e: + print("RPC failed to connect due to Discord not being opened yet.") + time.sleep(10) + +def check_mcbe(): + return 'MINECRAFT MAIN ' in (p.name() for p in psutil.process_iter()) + +# ----- Command-Line Arguments +mcbe_game=str(sys.argv[1]) + +# ----- Connect to RPC +connect_rpc() + +# ----- Config +local_time=time.localtime() +start_time=time.mktime(local_time) + +# ----- Loops +while True: + try: + if check_mcbe() == True: + RPC.update(details=mcbe_game, large_image='minecraft', start=start_time) + print('RPC has been updated.') + time.sleep(5) + else: + print('Minecraft is not running') + break + except KeyboardInterrupt as kb: + print('RPC interrupted') + break diff --git a/.local/bin/custom/mpv-link b/.local/bin/custom/mpv-link new file mode 100755 index 0000000..e180ff0 --- /dev/null +++ b/.local/bin/custom/mpv-link @@ -0,0 +1,4 @@ +#!/bin/sh + +link=$(echo "$(xclip -selection clipboard -o)" | dmenu -i -p "Link: ") +[ -z $link ] && exit 1 || mpv $link diff --git a/.local/bin/custom/netcheck b/.local/bin/custom/netcheck new file mode 100755 index 0000000..3b0ecde --- /dev/null +++ b/.local/bin/custom/netcheck @@ -0,0 +1,3 @@ +#!/bin/sh + +sudo nmap -sn 10.0.0.0/27 | awk '/10\./; /MAC/' | sed 's/^.* 10/IP Address: 10/g; s/MAC/^ MAC/g' && echo "^ (This PC)" diff --git a/.local/bin/custom/play b/.local/bin/custom/play new file mode 100755 index 0000000..c330ff4 --- /dev/null +++ b/.local/bin/custom/play @@ -0,0 +1,4 @@ +#!/bin/sh +gametype=$(echo "$(find "$HOME/my Games" -maxdepth 1 | sort | awk '!/s$/' | sed "s/^.*s\///")" | dmenu -i -p "Games") +[ -z $gametype ] && exit 1 +games -t "$gametype" diff --git a/.local/bin/custom/prepare_webcam b/.local/bin/custom/prepare_webcam new file mode 100755 index 0000000..bfe8002 --- /dev/null +++ b/.local/bin/custom/prepare_webcam @@ -0,0 +1,624 @@ +#!/bin/bash + +# Script for using IP Webcam as a microphone/webcam in Debian Jessie, +# Ubuntu 13.04, 14.04, 16.04 and Arch Linux + +# Copyright (C) 2011-2020 Antonio García Domínguez +# Copyright (C) 2016 C.J. Adams-Collier +# Copyright (C) 2016 Laptander +# Licensed under GPLv3 + +# Usage: ./prepare-videochat.sh [flip method] +# +# [flip method] is "none" by default. Here are some values you can try +# out (from gst/videofilter/gstvideoflip.c): +# +# - clockwise: clockwise 90 degrees +# - rotate-180: 180 degrees +# - counterclockwise: counter-clockwise 90 degrees +# - horizontal-flip: flip horizontally +# - vertical-flip: flip vertically +# - upper-left-diagonal: flip across upper-left/lower-right diagonal +# - upper-right-diagonal: flip across upper-right/lower-left diagonal +# +# However, some of these flip methods do not seem to work. In +# particular, those which change the picture size, such as clockwise +# or counterclockwise. *-flip and rotate-180 do work, though. +# +# To be able to use audio from your phone as a virtual microphone, open pavucontrol, +# then open Playback tab and choose 'IP Webcam' for gst-launch-1.0 playback Stream. +# Then to use audio stream in Audacity, open it and press record button or click on +# the Recording Meter Toolbar to start monitoring, then go to pavucontrol's Recording tab +# and choose "Monitor of IP Webcam" for ALSA plug-in [audacity]. +# +# If you want to be able to hear other applications sounds, for example from web-browser, +# then while it is playing some sound, go to pavucontrol's Playback tab and choose your +# default sound card for web-browser. + +# +# INSTALLATION +# +# In Arch Linux +# install ipwebcam-gst-git package from AUR +# +# MULTIPLE WEBCAMS +# +# This requires some extra work. First, you need to reload the +# v4l2loopback module yourself and specify how many loopback devices +# you want (default is 1). For instance, if you want 2: +# +# sudo modprobe -r v4l2loopback +# sudo modprobe v4l2loopback exclusive_caps=1 devices=2 +# +# Next, run two copies of this script with explicit WIFI_IP and DEVICE +# settings (see CONFIGURATION): +# +# ./prepare-videochat.sh +# ./prepare-videochat-copy.sh +# +# TROUBLESHOOTING +# +# 1. Does v4l2loopback work properly? +# +# Try running these commands. You'll first need to install mplayer and +# ensure that your user can write to /dev/video*). +# +# sudo modprobe -r v4l2loopback +# ls /dev/video* +# (Note down the devices available.) +# sudo modprobe v4l2loopback exclusive_caps=1 +# ls /dev/video* +# (Note down the new devices: let X be the number of the first new device.) +# v4l2-ctl -D -d /dev/videoX +# gst-launch-1.0 videotestsrc ! v4l2sink device=/dev/videoX & mplayer -tv device=/dev/videoX tv:// +# +# +# You should be able to see the GStreamer test video source, which is +# like a TV test card. Otherwise, there's an issue in your v4l2loopback +# installation that you should address before using this script. +# +# 2. Does the video connection work properly? +# +# To make sure the video from IP Webcam works for you (except for +# v4l2loopback and your video conference software), try this command +# with a simplified pipeline (do not forget to replace $IP and $PORT +# with your values): +# +# on Debian: +# gst-launch-1.0 souphttpsrc location="http://$IP:$PORT/videofeed" \ +# do-timestamp=true is-live=true \ +# ! multipartdemux ! jpegdec ! ffmpegcolorspace ! ximagesink +# +# on Arch Linux: +# gst-launch-1.0 souphttpsrc location="http://$IP:$PORT/videofeed" \ +# do-timestamp=true is-live=true \ +# ! multipartdemux ! jpegdec ! videoconvert ! ximagesink +# +# You should be able to see the picture from your webcam on a new window. +# If that doesn't work, there's something wrong with your connection to +# the phone. +# +# 3. Are you plugging several devices into your PC? +# +# By default, the script assumes you're only plugging one device into +# your computer. If you're plugging in several Android devices to your +# computer, you will first need to tell this script which one should +# be used. Run 'adb devices' with only the desired device plugged in, +# and note down the identifer. +# +# Then, uncomment the line that adds the -s flag to ADB_FLAGS below, +# replacing 'deviceid' with the ID you just found, and run the script +# normally. +# +# -- +# +# Last tested with: +# - souphttpsrc version 1.0.6 +# - v4l2sink version 1.0.6 +# - v4l2loopback version 0.7.0 + +# Exit on first error +set -e + +if [ -n "$1" ]; then + FLIP_METHOD=$1 +else + FLIP_METHOD=none +fi + +GST_FLIP="! videoflip method=\"$FLIP_METHOD\" " +if [ $FLIP_METHOD = 'none' ]; then + GST_FLIP="" +fi + +### CONFIGURATION + +# If your "adb" is not in your $PATH, set the full path to it here. +# If "adb" is in your $PATH, you don't have to change this option. +ADB_PATH=~/bin/android-sdk-linux_x86/platform-tools/adb +if which adb > /dev/null ; then + ADB=$(which adb) +elif [ -f $ANDROID_SDK_ROOT/platform-tools/adb ] ; then + ADB=$ANDROID_SDK_ROOT/platform-tools/adb +elif [ -f $ANDROID_HOME/platform-tools/adb ] ; then + ADB=$ANDROID_HOME/platform-tools/adb +else + ADB=$ADB_PATH +fi + +# Flags for ADB. +ADB_FLAGS= +#ADB_FLAGS="$ADB_FLAGS -s deviceid" # use when you need to pick from several devices (check deviceid in 'adb devices') + +# idea: make ability to choose IP version (usefull for IPv6-only environment) +# IP_VERSION=4 + +# IP used by the phone in your wireless network +WIFI_IP=192.168.2.140 + +# Port on which IP Webcam is listening +PORT=8080 + +# To disable proxy while acessing WIFI_IP (set value 1 to disable, 0 for not) +# For cases when host m/c is connected to a Proxy-Server and WIFI_IP belongs to local network +DISABLE_PROXY=0 + +# Dimensions of video +WIDTH=640 +HEIGHT=480 + +# Frame rate of video +GST_FPS=24 + +# Choose audio codec from wav, aac or opus +# do not choose opus until editing pipeline. If choose opus, pipeline will not work +# and some errors will appear in feed.log. +# I do not know how to edit pipelines for now. +AUDIO_CODEC=wav + +# Choose which stream to capture. +# a - audio only, v - video only, av - audio and video. +# Make sure that IP webcam is streaming corresponding streams, otherwise error will occur. +CAPTURE_STREAM=av + +# Loopback device to be used. This only needs to be uncommented if you +# want to skip autodetection (e.g. for multiple webcams): +#DEVICE=/dev/video0 + +# Force syncing to timestamps. Useful to keep audio and video in sync, +# but may impact performance in slow connections. If you see errors about +# timestamping or you do not need audio, you can try changing this to false. +SYNC=true + +# Options for loading the v4l2loopback: +# * use of exclusive_caps=1 is recommended in v4l2loopback#78 +V4L2_OPTS="exclusive_caps=1 card_label=\"IP Webcam\"" + +### FUNCTIONS + +has_kernel_module() { + # Checks if module exists in system (but does not load it) + MODULE="$1" + if lsmod | grep -w "$MODULE" >/dev/null 2>/dev/null; then + # echo "$MODULE is loaded! So it exists." + return 0 + else + # Determining kernel object existence + # I do not know why, but using -q in egrep makes it always return 1, so do not use it + if [ `find /lib/modules/$(uname -r)/ -name "$MODULE.ko*" | egrep '.*' || + find /lib/modules/$(uname -r)/extra -name "$MODULE.ko*" | egrep '.*'|| + find /lib/modules/$(uname -r)/extramodules -name "$MODULE.ko*" | egrep '.*'` ]; then + return 0 + else + return 1 + fi + fi + +} + +check_os_version() { + # checks if the OS version can use newer GStreamer version + DIST="$1" + RELEASE="$2" + + case "$DIST" in + "Debian") return "`echo "$RELEASE < 8.0" | bc`" ;; + "Ubuntu") return "`echo "$RELEASE < 14.04" | bc`" ;; + "LinuxMint") return "`echo "$RELEASE < 14.04" | bc`" ;; + "Arch") return 0 ;; + esac + # assume other Distributions are also new enough, by now + return 0 +} + +error() { + zenity --error --no-wrap --text "$@" > /dev/null 2>&1 + exit 1 +} + +warning() { + zenity --warning --no-wrap --text "$@" > /dev/null 2>&1 +} + +info() { + zenity --info --no-wrap --text "$@" > /dev/null 2>&1 +} + +confirm() { + zenity --question --no-wrap --text "$@" > /dev/null 2>&1 +} + +can_run() { + # It's either the path to a file, or the name of an executable in $PATH + which "$1" >/dev/null 2>/dev/null +} + +install_package() { + if [ $DIST = "Debian" ] || [ $DIST = "Ubuntu" ] || [ $DIST = "LinuxMint" ]; then + echo "Trying to install $1 package." + sudo apt-get install -y "$1" + elif [ $DIST = "Arch" ]; then + echo "Please install $1 package" 1>&2 + exit 1 + fi +} + +start_adb() { + can_run "$ADB" && "$ADB" $ADB_FLAGS start-server +} + +phone_plugged() { + test "$("$ADB" $ADB_FLAGS get-state 2>/dev/null)" = "device" +} + +url_reachable() { + if ! can_run curl && can_run apt-get; then + # Some versions of Ubuntu do not have curl by default (Arch + # has it in its core, so we don't need to check that case) + sudo apt-get install -y curl + fi + + CURL_OPTIONS="" + if [ $DISABLE_PROXY = 1 ]; then + CURL_OPTIONS="--noproxy $WIFI_IP" + fi + + # -f produces a non-zero status code when answer is 4xx or 5xx + curl $CURL_OPTIONS -f -m 5 -sI "$1" >/dev/null +} + +iw_server_is_started() { + if [ $CAPTURE_STREAM = av ]; then + : # help me optimize this code + temp=$(url_reachable "$AUDIO_URL"); au=$?; #echo au=$au + temp=$(url_reachable "$VIDEO_URL"); vu=$?; #echo vu=$vu + if [ $au = 0 -a $vu = 0 ]; then return 0; else return 1; fi + elif [ $CAPTURE_STREAM = a ]; then + if url_reachable "$AUDIO_URL"; then return 0; else return 1; fi + elif [ $CAPTURE_STREAM = v ]; then + if url_reachable "$VIDEO_URL"; then return 0; else return 1; fi + else + error "Incorrect CAPTURE_STREAM value ($CAPTURE_STREAM). Should be a, v or av." + fi +} + +start_iw_server() { + # Note: recent versions of IP Webcam do not export the Rolling intent due + # to security reasons. Users will have to start that on their own. + echo "Please start IP Webcam or IP Webcam Pro server and press Enter" + read + sleep 2s +} + +module_id_by_sinkname() { + pacmd list-sinks | grep -e 'name:' -e 'module:' | grep -A1 "name: <$1>" | grep module: | cut -f2 -d: | tr -d ' ' +} + +# is this function needed somewhere? +module_id_by_sourcename() { + pacmd list-sources | grep -e 'name:' -e 'module:' | grep -A1 "name: <$1>" | grep module: | cut -f2 -d: | tr -d ' ' +} + +declare -A DISTS +DISTS=(["Debian"]=1 ["Ubuntu"]=2 ["Arch"]=3 ["LinuxMint"]=4) + +if can_run lsb_release; then + DIST=`lsb_release -i | cut -f2 -d ":"` + RELEASE=`lsb_release -r | cut -f2 -d ":"` +fi +if [ -z "$DIST" ] || [ -z "${DISTS[$DIST]}" ] ; then + if [ -f "/etc/arch-release" ]; then + DIST="Arch" + RELEASE="" + elif [ -f "/etc/debian_version" ] ; then + DIST="Debian" + RELEASE=`perl -ne 'chomp; if(m:(jessie|testing|sid):){print "8.0"}elsif(m:[\d\.]+:){print}else{print "0.0"}' < /etc/debian_version` + fi +fi + +GST_VER="0.10" +GST_VIDEO_CONVERTER="ffmpegcolorspace" +GST_VIDEO_MIMETYPE="video/x-raw-yuv" +GST_VIDEO_FORMAT="format=(fourcc)YUY2" + +GST_AUDIO_MIMETYPE="audio/x-raw-int" +GST_AUDIO_FORMAT="width=16,depth=16,endianness=1234,signed=true" +GST_AUDIO_RATE="rate=44100" +GST_AUDIO_CHANNELS="channels=1" +GST_AUDIO_LAYOUT="" + +GST_1_0_AUDIO_FORMAT="format=S16LE" +GST_0_10_VIDEO_MIMETYPE=$GST_VIDEO_MIMETYPE +GST_0_10_VIDEO_FORMAT=$GST_VIDEO_FORMAT + +if ! can_run bc; then + install_package bc +fi + +set +e +check_os_version $DIST $RELEASE +set -e +if [ $? -eq 0 ] +then + GST_VER="1.0" + GST_VIDEO_CONVERTER="videoconvert" + GST_VIDEO_MIMETYPE="video/x-raw" + GST_VIDEO_FORMAT="format=YUY2" + + GST_AUDIO_MIMETYPE="audio/x-raw" + GST_AUDIO_FORMAT=$GST_1_0_AUDIO_FORMAT + GST_AUDIO_LAYOUT=",layout=interleaved" +fi + +DIMENSIONS="width=$WIDTH,height=$HEIGHT" + +GST_0_10_VIDEO_CAPS="$GST_0_10_VIDEO_MIMETYPE,$GST_0_10_VIDEO_FORMAT,$DIMENSIONS" +GST_VIDEO_CAPS="$GST_VIDEO_MIMETYPE,$GST_VIDEO_FORMAT,$DIMENSIONS" +GST_AUDIO_CAPS="$GST_AUDIO_MIMETYPE,$GST_AUDIO_FORMAT$GST_AUDIO_LAYOUT,$GST_AUDIO_RATE,$GST_AUDIO_CHANNELS" +PA_AUDIO_CAPS="$GST_AUDIO_FORMAT $GST_AUDIO_RATE $GST_AUDIO_CHANNELS" + +# GStreamer debug string (see gst-launch manpage) +GST_DEBUG=souphttpsrc:0,videoflip:0,$GST_CONVERTER:0,v4l2sink:0,pulse:0 +# Is $GST_CONVERTER defined anywhere? Maybe you mean videoconvert vs ffmpegcolorspace? It is in GST_VIDEO_CONVERTER + +### MAIN BODY + + +if ! can_run zenity; then + install_package zenity +fi + +# Check if the user has v4l2loopback +if ! has_kernel_module v4l2loopback; then + if [ $DIST = "Debian" ] || [ $DIST = "Ubuntu" ] || [ $DIST = "Arch" ]; then + install_package "v4l2loopback-dkms" + if [ $DIST = "Ubuntu" ]; then + install_package "python-apport" + fi + + if [ $? != 0 ]; then + info "Installation failed. Please install v4l2loopback manually from github.com/umlaeute/v4l2loopback." + fi + fi + + if has_kernel_module v4l2loopback; then + info "The v4l2loopback kernel module was installed successfully." + else + error "Could not install the v4l2loopback kernel module through apt-get." + fi +fi + +# Probe module if not probed yet +if lsmod | grep -w v4l2loopback >/dev/null 2>/dev/null; then + # module is already loaded, do nothing + : +elif [ $CAPTURE_STREAM = v -o $CAPTURE_STREAM = av ]; then + echo Loading module + sudo modprobe v4l2loopback $V4L2_OPTS #-q > /dev/null 2>&1 +fi + +# check if the user has the pulse gst plugin installed +if find "/usr/lib/gstreamer-$GST_VER/libgstpulseaudio.so" "/usr/lib/gstreamer-$GST_VER/libgstpulse.so" "/usr/lib/$(uname -m)-linux-gnu/gstreamer-$GST_VER/libgstpulse.so" 2>/dev/null | egrep -q '.*'; then + # plugin installed, do nothing + # info "Found the pulse gst plugin" + : +else + if [ $DIST = "Debian" ] || [ $DIST = "Ubuntu" ]; then + install_package "gstreamer${GST_VER}-pulseaudio" + elif [ $DIST = "Arch" ]; then + install_package "gst-plugins-good" + fi +fi + +# If the user hasn't manually specified which /dev/video* to use +# through DEVICE, use the first "v4l2 loopback" device as the webcam: +# this should help when loading v4l2loopback on a system that already +# has a regular webcam. If that doesn't work, fall back to /dev/video0. +if ! can_run v4l2-ctl; then + install_package v4l-utils +fi +if [ -z "$DEVICE" ]; then + if can_run v4l2-ctl; then + for d in /dev/video*; do + if v4l2-ctl -d "$d" -D | grep -q "v4l2 loopback"; then + DEVICE=$d + break + fi + done + fi + if [ -z "$DEVICE" ]; then + DEVICE=/dev/video0 + warning "Could not find the v4l2loopback device: falling back to $DEVICE" + fi +fi + +# Test that we can read from and write to the device +if ! test -r "$DEVICE"; then + error "$DEVICE is not readable: please fix your permissions" +fi +if ! test -w "$DEVICE"; then + error "$DEVICE is not writable: please fix your permissions" +fi + +# Decide whether to connect through USB or through wi-fi +IP=$WIFI_IP +if ! can_run "$ADB"; then + warning "adb is not available: you'll have to use Wi-Fi, which will be slower. Next time, please install the Android SDK from developer.android.com/sdk or install adb package in Ubuntu" +else + while ! phone_plugged && ! confirm "adb is available, but the phone is not plugged in. Are you sure you want to use Wi-Fi (slower)?\nIf you don't, please connect your phone to USB and allow usb debugging under developer settings."; do + true + sleep 1; + done + if phone_plugged; then + if ss -ln src :$PORT | grep -q :$PORT; then + warning "Your port $PORT seems to be in use: falling back to Wi-Fi. If you would like to use USB forwarding, please free it up and try again." + else + "$ADB" $ADB_FLAGS forward tcp:$PORT tcp:$PORT + IP=127.0.0.1 + fi + fi +fi + +BASE_URL=http://$IP:$PORT +VIDEO_URL=$BASE_URL/videofeed +AUDIO_URL=$BASE_URL/audio.$AUDIO_CODEC + +# start adb daemon to avoid relaunching it in while +if can_run "$ADB"; then + start_adb +fi + +# Remind the user to open up IP Webcam and start the server +if phone_plugged && ! iw_server_is_started; then + # If the phone is plugged to USB and we have ADB, we can start the server by sending an intent + start_iw_server +fi + +while ! iw_server_is_started; do + if [ $CAPTURE_STREAM = av ]; then + MESSAGE="The IP Webcam audio feed is not reachable at $AUDIO_URL.\nThe IP Webcam video feed is not reachable at $VIDEO_URL." + elif [ $CAPTURE_STREAM = a ]; then + MESSAGE="The IP Webcam audio feed is not reachable at $AUDIO_URL." + elif [ $CAPTURE_STREAM = v ]; then + MESSAGE="The IP Webcam video feed is not reachable at $VIDEO_URL." + else + error "Incorrect CAPTURE_STREAM value ($CAPTURE_STREAM). Should be a, v or av." + fi + info "$MESSAGE\nPlease install and open IP Webcam in your phone and start the server.\nMake sure that values of variables IP, PORT, CAPTURE_STREAM in this script are equal with settings in IP Webcam." +done + +# idea: check if default-source is correct. If two copy of script are running, +# then after ending first before second you will be set up with $SINK_NAME.monitor, +# but not with your original defauld source. +# The same issue if script was not end correctly, and you restart it. +DEFAULT_SINK=$(pacmd dump | grep set-default-sink | cut -f2 -d " ") +DEFAULT_SOURCE=$(pacmd dump | grep set-default-source | cut -f2 -d " ") + +SINK_NAME="ipwebcam" +SINK_ID=$(module_id_by_sinkname $SINK_NAME) +ECANCEL_ID=$(module_id_by_sinkname "${SINK_NAME}_echo_cancel") + +# Registering audio device if not yet registered +if [ -z $SINK_ID ] ; then + SINK_ID=$(pactl load-module module-null-sink \ + sink_name="$SINK_NAME" \ + $PA_AUDIO_CAPS \ + sink_properties="device.description='IP\ Webcam'") +fi + +if [ -z $ECANCEL_ID ] ; then + ECANCEL_ID=$(pactl load-module module-echo-cancel \ + sink_name="${SINK_NAME}_echo_cancel" \ + source_master="$SINK_NAME.monitor" \ + sink_master="$DEFAULT_SINK" \ + $PA_AUDIO_CAPS \ + aec_method="webrtc" save_aec=true use_volume_sharing=true) || true +fi + +pactl set-default-source $SINK_NAME.monitor + +# Check for gst-launch +GSTLAUNCH=gst-launch-${GST_VER} +if [ $DIST = "Debian" ] || [ $DIST = "Ubuntu" ]; then + if ! can_run "$GSTLAUNCH"; then + install_package gstreamer${GST_VER}-tools + fi +elif [ $DIST = "Arch" ]; then + if ! can_run "$GSTLAUNCH"; then + error "You don't have gst-launch. Please install gstreamer and gst-plugins-good packages." + fi +fi +if ! can_run "$GSTLAUNCH"; then + error "Could not find gst-launch. Exiting." + # exit 1 # you have already exited after error function. +fi + +# Start the GStreamer graph needed to grab the video and audio +set +e + +#sudo v4l2loopback-ctl set-caps $GST_0_10_VIDEO_CAPS $DEVICE + +pipeline_video() { + echo souphttpsrc location="$VIDEO_URL" do-timestamp=true is-live=true \ + ! queue \ + ! multipartdemux \ + ! decodebin \ + $GST_FLIP \ + ! $GST_VIDEO_CONVERTER \ + ! videoscale \ + ! $GST_VIDEO_CAPS \ + ! v4l2sink device="$DEVICE" sync=$SYNC +} + +pipeline_audio() { + echo souphttpsrc location="$AUDIO_URL" do-timestamp=true is-live=true \ + ! $GST_AUDIO_CAPS ! queue \ + ! pulsesink device="$SINK_NAME" sync=$SYNC +} + +if [ $CAPTURE_STREAM = av ]; then + PIPELINE="$( pipeline_audio ) $( pipeline_video )" +elif [ $CAPTURE_STREAM = a ]; then + PIPELINE=$( pipeline_audio ) +elif [ $CAPTURE_STREAM = v ]; then + PIPELINE=$( pipeline_video ) +else + error "Incorrect CAPTURE_STREAM value ($CAPTURE_STREAM). Should be a, v or av." +fi + +# echo "$PIPELINE" + +if [ $DISABLE_PROXY = 1 ]; then + # Disabling proxy to access WIFI_IP viz. on local network + unset http_proxy +fi + +"$GSTLAUNCH" -e -vt --gst-plugin-spew \ + --gst-debug="$GST_DEBUG" \ + $PIPELINE \ + >feed.log 2>&1 & + # Maybe we need edit this pipeline to transfer it to "Monitor of IP Webcam" to be able to use it as a microphone? + +GSTLAUNCH_PID=$! + +if [ $CAPTURE_STREAM = av ]; then + MESSAGE="IP Webcam audio is streaming through pulseaudio sink '$SINK_NAME'.\nIP Webcam video is streaming through v4l2loopback device $DEVICE.\n" +elif [ $CAPTURE_STREAM = a ]; then + MESSAGE="IP Webcam audio is streaming through pulseaudio sink '$SINK_NAME'.\n" +elif [ $CAPTURE_STREAM = v ]; then + MESSAGE="IP Webcam video is streaming through v4l2loopback device $DEVICE.\n" +else + error "Incorrect CAPTURE_STREAM value ($CAPTURE_STREAM). Should be a, v or av." +fi +info "$MESSAGE You can now open your videochat app." + +echo "Press enter to end stream" +perl -e '' + +kill $GSTLAUNCH_PID > /dev/null 2>&1 || echo "" +pactl set-default-source ${DEFAULT_SOURCE} +pactl unload-module ${ECANCEL_ID} +pactl unload-module ${SINK_ID} + +echo "Disconnected from IP Webcam. Have a nice day!" +# idea: capture ctrl-c signal and set default source back diff --git a/.local/bin/custom/twitch-dmenu b/.local/bin/custom/twitch-dmenu new file mode 100755 index 0000000..a3c62bd --- /dev/null +++ b/.local/bin/custom/twitch-dmenu @@ -0,0 +1,6 @@ +#!/bin/sh + +link="https://twitch.tv/$(echo "" | dmenu -p "Channel/Video: ")" +[ -z $link ] && exit 1 + +mpv $link && echo "Successfully load" || notify-send "Channel/video name is invalid or offline"