#!/usr/bin/env python
# title				: current_song.py
# description		: VLC Current Song is an OBS script that will update a Text Source
#					: with the current song that VLC is playing.
# author			: Enzo Innocenzi (Hawezo)
# date				: 2018 04 01
# version			: 0.1
# usage				: python pyscript.py
# dependencies		: - Python 3.6 (https://www.python.org/)
# 					: 	- requests (http://www.python-requests.org/)
# notes				: Follow this step for this script to work:
# 					: Python:
# 					:	1. Install python (64 bits, this is important)
# 					:	2. Install requests
# 					:		- Open a command prompt with administrator privileges
# 					:		- Type in "pip install requests"
#					:
# 					: VLC:
# 					:	1. Go to Tools › Preferences
# 					:	2. Select the "All" radio button on the bottom left
# 					:	3. Click "Main Interfaces" in the list
# 					:	4. Check the "Web' checkbox
# 					:	5. Expand "Main Interfaces", select "Lua"
# 					:	6. Set a password in the Lua HTTP groupbox
# 					:	7. Make sure "Source directory" as a value similar to
# 					:		"C:\Program Files (x86)\VideoLAN\VLC\lua\http"
# 					:	8. Save settings and restart VLC
# 					:
# 					: OBS:
# 					:	1. Create a GDI+ Text Source with the name of your choice
# 					:	2. Go to Tools › Scripts
# 					:	3. Click the "+" button and add this script
# 					:	4. Set the same password as the one in VLC
# 					:	5. Set the same source name as the one you just created
# 					:	6. Check "Enable"
# 					:	7. Click the "Python Settings" rab
# 					:	8. Select your python install path
# 					:
# python_version	: 3.6+
# ==============================================================================

import obspython as obs
import os, time, datetime, requests, codecs
import xml.etree.ElementTree as ET

try:
	from HTMLParser import HTMLParser
except ImportError:
	from html.parser import HTMLParser

working = True
enabled = True
now_playing = ''
check_frequency = 300
display_text = 'Current song: %title - %artist'
debug_mode = False

source_name = ''

http_username = ''
http_password = ''
http_url = 'http://localhost:8080/requests/status.xml'


# ------------------------------------------------------------
# OBS Script Functions
# ------------------------------------------------------------

def script_defaults(settings):
	global debug_mode
	if debug_mode: print("Calling defaults")

	global enabled
	global source_name
	global display_text
	global check_frequency
	global http_username
	global http_password
	global http_url
	
	obs.obs_data_set_default_bool(settings, "enabled", enabled)
	obs.obs_data_set_default_int(settings, "check_frequency", check_frequency)
	obs.obs_data_set_default_string(settings, "display_text", display_text)
	obs.obs_data_set_default_string(settings, "source_name", source_name)
	obs.obs_data_set_default_string(settings, "http_username", http_username)
	obs.obs_data_set_default_string(settings, "http_password", http_password)
	obs.obs_data_set_default_string(settings, "http_url", http_url)
	

def script_description():
	global debug_mode
	if debug_mode: print("Calling description")

	return "<b>VLC Now Playing</b>" + \
		"<hr>" + \
		"Display current song as a text on your screen." + \
		"<br/>" + \
		"For this to work, you have to set up VLC http lua broadcasting." + \
		"<br/><br/>" + \
		"Available placeholders: " + \
		"<br/>" + \
		"<code>%artist</code>, <code>%title</code>, <code>%filename</code>" + \
		"<br/><br/>" + \
		"Thanks to Tipher88 for his original script." + \
		"<br/>" + \
		"Adapted to OBS by Hawezo (hawezo.xyz)" + \
		"<hr>"

def script_load(settings):
	global debug_mode
	if debug_mode: print("[VLC CS] Loaded script.")
	
def script_properties():
	global debug_mode
	if debug_mode: print("[VLC CS] Loaded properties.")

	props = obs.obs_properties_create()
	obs.obs_properties_add_bool(props, "enabled", "Enabled")
	obs.obs_properties_add_bool(props, "debug_mode", "Debug Mode")
	obs.obs_properties_add_int(props, "check_frequency", "Check frequency", 150, 10000, 100 )
	obs.obs_properties_add_text(props, "display_text", "Display text", obs.OBS_TEXT_DEFAULT )
	obs.obs_properties_add_text(props, "source_name", "Text source", obs.OBS_TEXT_DEFAULT )
	obs.obs_properties_add_text(props, "http_username", "HTTP Username", obs.OBS_TEXT_DEFAULT )
	obs.obs_properties_add_text(props, "http_password", "HTTP Password", obs.OBS_TEXT_DEFAULT )
	obs.obs_properties_add_text(props, "http_url", "HTTP URL", obs.OBS_TEXT_DEFAULT )
	obs.obs_properties_add_text(props, "display_text", "Display text", obs.OBS_TEXT_DEFAULT )
	return props

def script_save(settings):
	global debug_mode
	if debug_mode: print("[VLC CS] Saved properties.")

	script_update(settings)

def script_unload():
	global debug_mode
	if debug_mode: print("[VLC CS] Unloaded script.")
	
	obs.timer_remove(get_song_info)

def script_update(settings):
	global debug_mode
	if debug_mode: print("[VLC CS] Updated properties.")

	global enabled
	global display_text
	global check_frequency
	global http_username
	global http_password
	global http_url
	global source_name
	
	if obs.obs_data_get_bool(settings, "enabled") is True:
		if (not enabled):
			if debug_mode: print("[VLC CS] Enabled song timer.")

		enabled = True
		obs.timer_add(get_song_info, check_frequency)
	else:
		if (enabled):
			if debug_mode: print("[VLC CS] Disabled song timer.")

		enabled = False
		obs.timer_remove(get_song_info)
			
	debug_mode = obs.obs_data_get_bool(settings, "debug_mode")
	display_text = obs.obs_data_get_string(settings, "display_text")
	http_username = obs.obs_data_get_string(settings, "http_username")
	http_password = obs.obs_data_get_string(settings, "http_password")
	http_url = obs.obs_data_get_string(settings, "http_url")
	source_name = obs.obs_data_get_string(settings, "source_name")
	check_frequency = obs.obs_data_get_int(settings, "check_frequency")

	
# ------------------------------------------------------------
# NowPlaying functions
# ------------------------------------------------------------


def get_song_info():

	global debug_mode
	global working
	global now_playing
	global display_text
	global check_frequency
	global http_username
	global http_password
	global http_url
	
	song_artist = '-'
	song_title = '-'
	now_playing = '-'
	file_name = ' '
	
	s = requests.Session()
	s.auth = (http_username, http_password)
	
	try:
		r = s.get(http_url, verify=False)
		
		if ('401 Client error' in r.text):
			if (working):
				working = False
				if debug_mode: print('[VLC CS] ERROR - Is VLC well configured? Are VLC CS\' properties well configured?')
			return
	except:
		if (working):
			working = False
			if debug_mode: print('[VLC CS] ERROR - Is VLC started? Is it well configured? Is its Lua Server started? Are VLC CS\' properties well configured?')
		return
		
	working = True
	
	root = ET.fromstring(r.content)
	
	for info in root.iter('info'):
		name = info.get('name')
		
		if(name == 'now_playing'):
			now_playing = info.text
		else:
			if(name == 'artist'):
				song_artist = info.text
			if(name == 'title'):
				song_title = info.text
			if(name == 'filename'):
				file_name = info.text
				file_name = os.path.splitext(file_name)[0]

	if (now_playing == '-'):
	
		if (song_title != '-' and song_artist != '-'):
		   now_playing = display_text.replace('%artist', song_artist).replace('%title', song_title).replace('%filename', file_name)
		   
		elif (song_title != '-'):
			now_playing = song_title
		
		elif( file_name != '-' ):
			now_playing = file_name
			
		else:
			now_playing = ''
	
	update_song()

def update_song():
	global debug_mode
	global now_playing
	
	settings = obs.obs_data_create()
	obs.obs_data_set_string(settings, "text", now_playing)
	source = obs.obs_get_source_by_name(source_name)
	obs.obs_source_update(source, settings)
	obs.obs_data_release(settings)
	obs.obs_source_release(source)
