zoukankan      html  css  js  c++  java
  • 树莓派实现只有一个按键的播放器


    因为家里老人不会用智能设备,所以做了一个超级简易的播放器。


    要实现的功能有

    1.拔电恢复

    2.视频列表切换恢复

    3.一键切换

    4.自动切换电视剧

    5.开机启动自动登录播放



    先来看看开机自动登录吧:



    实现自动登录:修改/etc/inittab文件
    sudo nano /etc/inittab
    向下滚动,找到行               1:2345:respawn:/sbin/getty 115200 tty1
    注释掉这一行,修改为       #1:2345:respawn:/sbin/getty 115200 tty1
    在该行下增加一行内容       1:2345:respawn:/bin/login -f pi tty1 </dev/tty1 >/dev/tty1 2>&1
    按Ctrl+X退出,记得按Y键保存
    原理:linux启动时,会读取inittab文件,执行其中的登录命令,以pi用户名自动登录



    开机启动:


    首先要开机挂载硬盘,不然无法播放视频:

    开机挂载

    /home/pi/start.sh 中写入下面的语句:
    sudo -i
    fdisk -l
    mount /dev/sda1 /media/mymovie

    其实用其他方式也可以的,后来也懒得去修改了。


    开机启动

    在/etc/rc.local 里面添加 ./home/pi/start.sh

    然后start.sh里面添加播放脚本的运行



    硬件连接


    硬件连接必须先来,不然都没法调试了。

    按键连接


    这里是参考了帖子:http://hugozhu.myalert.info/2013/04/08/27-interrupts-with-gpio-pins.html


    整体视图



    程序代码


    对于这整个系统,代码显得尤其重要。下面先贴上代码:

    #!/usr/bin/env python2.7
    #coding=utf-8
    import os
    import subprocess,time
    import shutil
    import thread
    import string
    import RPi.GPIO as GPIO
    GPIO.setmode(GPIO.BCM)
    
    GPIO.setup(25,GPIO.IN,pull_up_down=GPIO.PUD_UP)
    
    global playProcess
    
    single_movie_arr=[]
    global single_movie_index
    
    folder_arr=[]
    global folder_index
    global movies_in_folder_index
    movies_in_folder_arr = []
    global setting_in_progress
    
    #1:folder 0:single
    global single_or_folder
    #1:manual 0:auto die
    global dead_reason
    
    root_dir = '/media/mymovie/movie'
    
    
    
    class record_last:
    	def __init__(self):
    		self.hour=0
    		self.minute=0
    		self.second=0
    		self.is_folder=1
    		self.index=0
    		self.reseting=0
    	
    global my_record#history
    global is_init
    
    
    def write_history(name,current_index):
    	f = file(os.path.join(name,'history.txt'),'w')
    	f.write(str(current_index))
    	f.close
    	#must read after write or srt will be empyy
    	f = file(os.path.join(name,'history.txt'),'r')
    	f.close
    
    def read_history(folder_name):
    	dest_file = os.path.join(folder_name,'history.txt')
    	if os.path.isfile(dest_file):
    		f = file(dest_file,'r')
    		line = f.readline()
    		print 'restore status:'+line
    		f.close
    		if line == '':
    			return 0
    		try:
    			return_val = int(line)
    		except:
    			return_val = 0
    		return return_val
    	else:
    		print 'restore status,no status'
    		return 0
    
    
    def auto_switch():
    	global playProcess,single_movie_arr,single_movie_index,folder_arr,folder_index,
    		movies_in_folder_index,setting_in_progress,single_or_folder,dead_reason,
    		root_dir,movies_in_folder_arr,is_init,my_record
    
    	print 'auto switching...'
    	if single_or_folder == 1:
    		if movies_in_folder_index < len(movies_in_folder_arr) - 1:
    			movies_in_folder_index = movies_in_folder_index + 1
    			play_movie(folder_arr[folder_index],movies_in_folder_index,1)
    		else:
    			#special case:last movie in folder,we need to delete status
    			write_history(folder_arr[folder_index],0);
    
    			if folder_index < len(folder_arr) - 1:
    
    				folder_index = folder_index + 1
    				movies_in_folder_index = read_history(folder_arr[folder_index])#need change
    				play_movie(folder_arr[folder_index],movies_in_folder_index,1)
    			elif len(single_movie_arr) > 0:
    				single_movie_index = 0
    				single_or_folder = 0
    				play_movie(single_movie_arr[single_movie_index],0,0)
    			else:
    				folder_index = 0
    				movies_in_folder_index = read_history(folder_arr[folder_index])#need change
    				play_movie(folder_arr[folder_index],movies_in_folder_index,1)		
    	else:
    		if single_movie_index < len(single_movie_arr) - 1:
    			single_movie_index = single_movie_index + 1
    			play_movie(single_movie_arr[single_movie_index],0,0)
    		elif len(folder_arr) > 0:
    			folder_index = 0
    			movies_in_folder_index = read_history(folder_arr[folder_index])#need change
    			single_or_folder = 1
    			play_movie(folder_arr[folder_index],movies_in_folder_index,1)
    		else:
    			single_movie_index = 0	
    			play_movie(single_movie_arr[single_movie_index],0,0)
    
    
    
    
    	
    
    
    
    def keyboard_event(thread_name):
    	global playProcess,single_movie_arr,single_movie_index,folder_arr,folder_index,
    		movies_in_folder_index,setting_in_progress,single_or_folder,dead_reason,
    		root_dir,movies_in_folder_arr,is_init,my_record
    	while 1:
    		#raw_input('')
    		try:
    			GPIO.wait_for_edge(25,GPIO.FALLING)
    			time.sleep(1)#in case on press causes multiple interrupts
    			setting_in_progress = 1
    			dead_reason = 1
    	
    			print 'switching...'
    			global playProcess
    			playProcess.stdin.write('q')
    			playProcess.stdin.flush()
    	
    			if single_or_folder == 1:
    				if folder_index < len(folder_arr) - 1:
    					folder_index = folder_index + 1
    					movies_in_folder_index = read_history(folder_arr[folder_index])#need change
    				elif len(single_movie_arr) > 0:
    					single_movie_index = 0
    					single_or_folder = 0
    				else:
    					folder_index = 0
    					movies_in_folder_index = read_history(folder_arr[folder_index])#need change
    			else:
    				if single_movie_index < len(single_movie_arr) - 1:
    					single_movie_index = single_movie_index + 1
    				elif len(folder_arr) > 0:
    					folder_index = 0
    					single_or_folder = 1
    					movies_in_folder_index = read_history(folder_arr[folder_index])#need change
    				else:
    					single_movie_index = 0
    	
    			setting_in_progress = 0
    		except KeyboardInterrupt:
    			time.sleep(1)
    			print 'GPIO fail!'
    			GPIO.cleanup()
    				
    
    
    
    def init_list():
    	global playProcess,single_movie_arr,single_movie_index,folder_arr,folder_index,
    		movies_in_folder_index,setting_in_progress,single_or_folder,dead_reason,
    		root_dir,movies_in_folder_arr,is_init,my_record
    
    	#add files in root dir to the list
    	nlist = os.listdir(root_dir)
    	for name in nlist:
    	    cur_name = os.path.join(root_dir, name)
    	    isfile = os.path.isfile(cur_name)
    	    if isfile:
    		if name.endswith('.mp4') or name.endswith('.MP4'):
    			single_movie_arr.append(cur_name)
    	    else:
    		folder_arr.append(cur_name)
    	single_movie_arr.sort()
    
    	print 'singles :'
    	for i in range(0,len(single_movie_arr)):
    		print single_movie_arr[i]
    	print 'folders :'
    	for i in range(0,len(folder_arr)):
    		print folder_arr[i]
    
    
    
    	
    
    
    def player_folder(name,current_index):
    	global playProcess,single_movie_arr,single_movie_index,folder_arr,folder_index,
    		movies_in_folder_index,setting_in_progress,single_or_folder,dead_reason,
    		root_dir,movies_in_folder_arr,is_init,my_record
    
    	print 'playing folder:'+name
    	movies_in_folder_arr=[]
    	nlist = os.listdir(name)
    	for single_name in nlist:
    		cur_name = os.path.join(name, single_name)
    		if single_name.endswith('.mp4') or single_name.endswith('.MP4'):
    			movies_in_folder_arr.append(cur_name)
    	movies_in_folder_arr.sort()
    
    	#for i in range(0,len(movies_in_folder_arr)):
    	#	print movies_in_folder_arr[i]
    
    
    	write_history(name,current_index)
    
    	player_single(movies_in_folder_arr[current_index],current_index,len(movies_in_folder_arr))
    	
    
    
    def write_srt(name,current_index,total_num):
    	f = file('/media/mymovie/title/1.srt','w')
    	f.write('0
    ')
    	f.write('00:00:00,000 --> 00:00:10,000
    ')
    	if total_num == 1:
    		name = string.replace(name,'.mp4','',1)
    		name = string.replace(name,'.MP4','',1)
    		f.write('<b>正在播放 电影 '+name.split('/')[-1]+'<b>
    ')
    	else:
    		f.write('<b>正在播放 电视剧 '+name.split('/')[-2]+'<b>
    ')
    		f.write('<b>第'+str(current_index+1)+'集,共'+str(total_num)+'集<b>
    ')
    	f.close
    	#must read after write or srt will be empyy
    	f = file('/media/mymovie/title/1.srt','r')
    	f.close
    
    
    def player_single(name,current_index,total_num):
    	global playProcess,single_movie_arr,single_movie_index,folder_arr,folder_index,
    		movies_in_folder_index,setting_in_progress,single_or_folder,dead_reason,
    		root_dir,movies_in_folder_arr,is_init,my_record
    
    	print 'playing:'+name
    	write_srt(name,current_index,total_num)
    	
    
    	if(is_init):
    		is_init = 0
    		pos_hour = str(my_record.hour)
    		pos_minute = str(my_record.minute)
    		pos_second = str(my_record.second)
    		if len(pos_hour) == 1:
    			pos_hour = '0'+pos_hour
    		if len(pos_minute) == 1:
    			pos_minute = '0'+pos_minute
    		if len(pos_second) == 1:
    			pos_second = '0'+pos_second
    		playProcess=subprocess.Popen(['omxplayer','--pos',pos_hour+':'+pos_minute+':'+pos_second,'--subtitles',
    			'/media/mymovie/title/1.srt','--font',
    			'/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc','--blank',name],
    			stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, close_fds=True)
    	else:
    		my_record.reseting = 1
    		playProcess=subprocess.Popen(['omxplayer','--subtitles','/media/mymovie/title/1.srt','--font',
    			'/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc','--blank',name],
    			stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, close_fds=True)
    	playProcess.wait()
    	
    
    
    def play_movie(name,current_index,is_folder):
    	if is_folder == 1:
    		player_folder(name,current_index)
    	else:
    		player_single(name,current_index,1)
    
    
    def record_thread(thread_name):
    	global playProcess,single_movie_arr,single_movie_index,folder_arr,folder_index,
    		movies_in_folder_index,setting_in_progress,single_or_folder,dead_reason,
    		root_dir,movies_in_folder_arr,is_init,my_record
    
    	while 1:
    		time.sleep(1)
    
    		if my_record.reseting == 1:
    			my_record.reseting = 0
    			my_record.hour = 0
    			my_record.minute = 0
    			my_record.second = 0
    
    
    		my_record.second = my_record.second + 1
    		if(my_record.second == 60):
    			my_record.minute = my_record.minute + 1
    			my_record.second = 0
    		if(my_record.minute == 60):
    			my_record.hour = my_record.hour + 1
    			my_record.minute = 0
    
    
    		dest_file = os.path.join(root_dir,'record.txt')
    		f = file(dest_file,'w')
    		f.write(str(single_or_folder)+'
    ')
    		if single_or_folder == 1:
    			f.write(str(folder_index)+'
    ')
    		else:
    			f.write(str(single_movie_index)+'
    ')
    		f.write(str(my_record.hour)+'
    ')
    		f.write(str(my_record.minute)+'
    ')
    		f.write(str(my_record.second)+'
    ')
    		f.close
    
    		#must read after write or srt will be empyy
    		f = file(dest_file,'r')
    		f.close
    
    def read_from_record_file():
    	dest_file = os.path.join(root_dir,'record.txt')
    	record = record_last() #new structure
    	if os.path.isfile(dest_file):
    		#read
    		f = file(dest_file,'r')
    		line = f.readline()#single_or_folder
    		if line != '':
    			try:
    				record.is_folder = int(line)
    				line = f.readline()#index
    				record.index = int(line)
    				line = f.readline()#hour
    				record.hour = int(line)
    				line = f.readline()#minute
    				record.minute = int(line)
    				line = f.readline()#second
    				record.second = int(line)
    			except:
    				record.hour=0
    				record.minute=0
    				record.second=0
    				record.is_folder=1
    				record.index=0	
    		else:
    			record.hour=0
    			record.minute=0
    			record.second=0
    			record.is_folder=1
    			record.index=0	
    
    		f.close
    	else:	
    		record.hour=0
    		record.minute=0
    		record.second=0
    		record.is_folder=1
    		record.index=0
    
    	record.reseting = 0
    	return record
    
    
    
    is_init = 1
    init_list()
    my_record = read_from_record_file()
    
    
    
    
    if my_record.is_folder == 1:
    	folder_index = my_record.index
    	movies_in_folder_index = read_history(folder_arr[folder_index])
    
    	single_or_folder = 1
    
    	single_movie_index = 0
    else:
    	folder_index = 0
    	movies_in_folder_index = 0
    
    	single_or_folder = 0
    
    	single_movie_index = my_record.index
    
    
    
    
    setting_in_progress = 0
    dead_reason = 1
    
    
    
    
    
    try:
    	thread.start_new_thread(keyboard_event,("Keyboard",))
    except:
    	print 'start thread error!'
    
    try:
    	thread.start_new_thread(record_thread,("Record Thread",))
    except:
    	print 'start thread error!'
    
    
    
    
    while 1:
    	while setting_in_progress == 1:
    		time.sleep(1)
    
    
    	if dead_reason == 1:
    		dead_reason = 0
    
    		if len(folder_arr) > 0 and single_or_folder == 1:
    			play_movie(folder_arr[folder_index],movies_in_folder_index,1)
    		elif len(single_movie_arr) > 0 and single_or_folder == 0:
    			play_movie(single_movie_arr[single_movie_index],0,0)
    		else:
    			print 'No any movie here!'
    			time.sleep(1000)
    	else:
    		auto_switch()	
    
    
    GPIO.cleanup()
    
    
    




    整个代码已经是比较短的了,下面一个个函数来分析吧:


    程序一开始执行read_from_record_file,这个函数的功能是读取上次记忆的功能,记忆的应该是文件的位置和电影的时间。

    由于时间久远已经不太记得它的格式了。



    if my_record.is_folder == 1:
    这个判断是判断是否记忆的是文件夹。这个程序支持在根目录放置文件和文件夹。若放置文件,则直接跳到那个文件播放,若放置文件夹,直接跳到文件夹对应的文件播放。

    它的目的是区分电影和电视剧。


    这一段的功能是开了两个线程,一个是记录按钮事件的,另一个是不断记录目前的进度,防止断电。

    try:
    	thread.start_new_thread(keyboard_event,("Keyboard",))
    except:
    	print 'start thread error!'
    
    try:
    	thread.start_new_thread(record_thread,("Record Thread",))
    except:
    	print 'start thread error!'
    




    这一片代码是判断是否dead。这里的dead的意思是是否按键切换。如果是按键切换则执行手动切换代码,否则的话执行auto_switch

    while 1:
    	while setting_in_progress == 1:
    		time.sleep(1)
    
    
    	if dead_reason == 1:
    		dead_reason = 0
    
    		if len(folder_arr) > 0 and single_or_folder == 1:
    			play_movie(folder_arr[folder_index],movies_in_folder_index,1)
    		elif len(single_movie_arr) > 0 and single_or_folder == 0:
    			play_movie(single_movie_arr[single_movie_index],0,0)
    		else:
    			print 'No any movie here!'
    			time.sleep(1000)
    	else:
    		auto_switch()	




    接下来看看上面的一些函数:


    record_thread

    这个是将当前进度写入到文件

    player_single

    是播放一个文件

    write_srt

    是一开始播放的时候注明这是第几集




    因为需要考虑到电影和电视剧,还有自动切换和手动切换。所以代码显得比较复杂。

    电影是放在根目录的,电视剧放在每个文件夹里面

    自动切换分为两种,第一种是电视剧间切换,另一种是电影间切换

    还要考虑到最后一个电视剧或者电影循环切回第一个。

    若不用python的话相信会用掉更多的代码。



    这个程序其实还可以改进,

    1.再加一个按钮,方便后退

    2.使用数据库记录历史数据

    3.自动调整电视剧在屏幕上的缩放比例

    4.断电恢复时也显示当前集数的字幕,而不是显示恢复播放

    5.切换电视剧的时候不重新开始而是播放记录的部分



  • 相关阅读:
    js常用框架原理
    移动端input解决键盘问题 方案1
    jq大体架构。先记录再慢慢剖析
    把图片存储 canvas原生API转成base64
    清除浮动的6中方法
    window.location.hash属性介绍
    前端性能优化之js,css调用优化
    数组中的对象,判断是否有重复值、
    [Python] Pitfalls: Be Careful with os.chdir
    Changing the Color of Linux ls Command 改变Linux的ls命令显示的颜色
  • 原文地址:https://www.cnblogs.com/tanhangbo/p/4282604.html
Copyright © 2011-2022 走看看