summaryrefslogtreecommitdiffstats
path: root/apps/media/lib_scanner.php
blob: ef63cea45dfe19fee69a5989d3ae3c448c485399 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
<?php

/**
* ownCloud - media plugin
*
* @author Robin Appelman
* @copyright 2010 Robin Appelman icewind1991@gmail.com
* 
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either 
* version 3 of the License, or any later version.
* 
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*  
* You should have received a copy of the GNU Lesser General Public 
* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
* 
*/

require_once('getID3/getid3/getid3.php');

//class for scanning directories for music
class OC_MEDIA_SCANNER{
	static private $getID3=false;
	
	//these are used to store which artists and albums we found, it can save a lot of addArtist/addAlbum calls
	static private $artists=array();
	static private $albums=array();//stored as "$artist/$album" to allow albums with the same name from different artists
	static private $useMp3Info=null;
	
	/**
	 * scan a folder for music
	 * @param string $path
	 * @return int the number of songs found
	 */
	public static function scanFolder($path){
		if (OC_Filesystem::is_dir($path)) {
			$songs=0;
			if ($dh = OC_Filesystem::opendir($path)) {
				while (($filename = readdir($dh)) !== false) {
					if($filename<>'.' and $filename<>'..' and substr($filename,0,1)!='.'){
						$file=$path.'/'.$filename;
						if(OC_Filesystem::is_dir($file)){
							$songs+=self::scanFolder($file);
						}elseif(OC_Filesystem::is_file($file)){
							$data=self::scanFile($file);
							if($data){
								$songs++;
							}
						}
					}
				}
			}
		}elseif(OC_Filesystem::is_file($path)){
			$songs=1;
			self::scanFile($path);
		}else{
			$songs=0;
		}
		return $songs;
	}

	/**
	 * scan a file for music
	 * @param string $path
	 * @return boolean
	 */
	public static function scanFile($path){
		if(is_null(self::$useMp3Info)){
			self::$useMp3Info=OC_Helper::canExecute("mp3info");
		}
		$file=OC_Filesystem::getLocalFile($path);
		if(substr($path,-3)=='mp3' and self::$useMp3Info){//use the command line tool id3info if possible
			$output=array();
			$size=filesize($file);
			exec('mp3info -p "%a\n%l\n%t\n%n\n%S" "'.$file.'"',$output);
			if(count($output)>4){
				$artist=$output[0];
				$album=$output[1];
				$title=$output[2];
				$track=$output[3];
				$length=$output[4];
			}else{
				return; //invalid mp3 file
			}
		}else{
			if(!self::isMusic($path)){
				return;
			}
			if(!self::$getID3){
				self::$getID3=@new getID3();
			}
			$data=@self::$getID3->analyze($file);
			getid3_lib::CopyTagsToComments($data);
			if(!isset($data['comments'])){
				OC_Log::write('media',"error reading id3 tags in '$file'",OC_Log::WARN);
				return;
			}
			if(!isset($data['comments']['artist'])){
				OC_Log::write('media',"error reading artist tag in '$file'",OC_Log::WARN);
				$artist='unknown';
			}else{
				$artist=stripslashes($data['comments']['artist'][0]);
				$artist=utf8_encode($artist);
			}
			if(!isset($data['comments']['album'])){
				OC_Log::write('media',"error reading album tag in '$file'",OC_Log::WARN);
				$album='unknown';
			}else{
				$album=stripslashes($data['comments']['album'][0]);
				$album=utf8_encode($album);
			}
			if(!isset($data['comments']['title'])){
				OC_Log::write('media',"error reading title tag in '$file'",OC_Log::WARN);
				$title='unknown';
			}else{
				$title=stripslashes($data['comments']['title'][0]);
				$title=utf8_encode($title);
			}
			$size=$data['filesize'];
			$track=(isset($data['comments']['track']))?$data['comments']['track'][0]:0;
			$length=isset($data['playtime_seconds'])?round($data['playtime_seconds']):0;
		}
		if(!isset(self::$artists[$artist])){
			$artistId=OC_MEDIA_COLLECTION::addArtist($artist);
			self::$artists[$artist]=$artistId;
		}else{
			$artistId=self::$artists[$artist];
		}
		if(!isset(self::$albums[$artist.'/'.$album])){
			$albumId=OC_MEDIA_COLLECTION::addAlbum($album,$artistId);
			self::$albums[$artist.'/'.$album]=$albumId;
		}else{
			$albumId=self::$albums[$artist.'/'.$album];
		}
		$songId=OC_MEDIA_COLLECTION::addSong($title,$path,$artistId,$albumId,$length,$track,$size);
		return (!($title=='unkown' && $artist=='unkown' && $album=='unkown'))?$songId:0;
	}

	/**
	 * quick check if a song is a music file by checking the extention, not as good as a proper mimetype check but way faster
	 * @param string $filename
	 * @return bool
	 */
	public static function isMusic($filename){
		$ext=substr($filename,strrpos($filename,'.')+1);
		return $ext=='mp3' || $ext=='flac' || $ext=='m4a' || $ext=='ogg' || $ext=='oga';
	}
}