ampache version 3.8.0 with add sql correction
correct docker sed /etc/hosts issue compatibilty with nginx 1.6
106
conf/admin.sql
|
@ -1 +1,107 @@
|
|||
INSERT INTO user(id,username,fullname,access) VALUES("", "yunoadmin", "yunoadmin", "100");
|
||||
|
||||
UPDATE `user_preference` SET `value` = 'fr_FR' WHERE `preference` = 31 ;
|
||||
|
||||
SET @lastid = LAST_INSERT_ID();
|
||||
|
||||
INSERT INTO `user_preference` (`user`, `preference`, `value`) VALUES
|
||||
(@lastid, 1, '1'),
|
||||
(@lastid, 4, '10'),
|
||||
(@lastid, 19, '32'),
|
||||
(@lastid, 22, 'Ampache :: For the love of Music'),
|
||||
(@lastid, 23, '0'),
|
||||
(@lastid, 24, '0'),
|
||||
(@lastid, 25, '80'),
|
||||
(@lastid, 41, 'mpd'),
|
||||
(@lastid, 29, 'web_player'),
|
||||
(@lastid, 31, 'fr_FR'),
|
||||
(@lastid, 32, 'm3u'),
|
||||
(@lastid, 33, 'reborn'),
|
||||
(@lastid, 34, '27'),
|
||||
(@lastid, 35, '27'),
|
||||
(@lastid, 36, '27'),
|
||||
(@lastid, 51, '50'),
|
||||
(@lastid, 40, '100'),
|
||||
(@lastid, 44, '1'),
|
||||
(@lastid, 45, '1'),
|
||||
(@lastid, 46, '1'),
|
||||
(@lastid, 47, '7'),
|
||||
(@lastid, 49, '1'),
|
||||
(@lastid, 52, '8192'),
|
||||
(@lastid, 53, 'default'),
|
||||
(@lastid, 55, 'default'),
|
||||
(@lastid, 57, ''),
|
||||
(@lastid, 69, '0'),
|
||||
(@lastid, 70, '0'),
|
||||
(@lastid, 71, '0'),
|
||||
(@lastid, 72, '0'),
|
||||
(@lastid, 73, ''),
|
||||
(@lastid, 74, ''),
|
||||
(@lastid, 75, ''),
|
||||
(@lastid, 76, ''),
|
||||
(@lastid, 77, ''),
|
||||
(@lastid, 78, ''),
|
||||
(@lastid, 114, '1'),
|
||||
(@lastid, 113, '0'),
|
||||
(@lastid, 112, '-1'),
|
||||
(@lastid, 111, '1'),
|
||||
(@lastid, 110, '0'),
|
||||
(@lastid, 109, '0'),
|
||||
(@lastid, 108, '0'),
|
||||
(@lastid, 107, '0'),
|
||||
(@lastid, 106, '0'),
|
||||
(@lastid, 105, '0'),
|
||||
(@lastid, 104, '0'),
|
||||
(@lastid, 103, '7'),
|
||||
(@lastid, 102, '0'),
|
||||
(@lastid, 101, '0'),
|
||||
(@lastid, 100, '1'),
|
||||
(@lastid, 99, '0'),
|
||||
(@lastid, 95, '1'),
|
||||
(@lastid, 94, '0'),
|
||||
(@lastid, 93, '1'),
|
||||
(@lastid, 92, '1'),
|
||||
(@lastid, 91, '1'),
|
||||
(@lastid, 90, '1'),
|
||||
(@lastid, 89, '1'),
|
||||
(@lastid, 88, '1'),
|
||||
(@lastid, 87, '0'),
|
||||
(@lastid, 86, '1'),
|
||||
(@lastid, 85, '1'),
|
||||
(@lastid, 84, '0'),
|
||||
(@lastid, 83, '0'),
|
||||
(@lastid, 79, '50'),
|
||||
(@lastid, 80, '50'),
|
||||
(@lastid, 82, '1'),
|
||||
(@lastid, 81, '1'),
|
||||
(@lastid, 115, '0'),
|
||||
(@lastid, 116, ''),
|
||||
(@lastid, 117, '1'),
|
||||
(@lastid, 118, '0'),
|
||||
(@lastid, 119, ''),
|
||||
(@lastid, 120, '0'),
|
||||
(@lastid, 121, '1'),
|
||||
(@lastid, 122, '1'),
|
||||
(@lastid, 123, '1'),
|
||||
(@lastid, 124, '0'),
|
||||
(@lastid, 125, '1'),
|
||||
(@lastid, 126, '1'),
|
||||
(@lastid, 127, '1'),
|
||||
(@lastid, 128, '1'),
|
||||
(@lastid, 129, ''),
|
||||
(@lastid, 130, 'album,ep,live,single'),
|
||||
(@lastid, 131, '1'),
|
||||
(@lastid, 132, '10'),
|
||||
(@lastid, 133, '0'),
|
||||
(@lastid, 134, '1'),
|
||||
(@lastid, 135, '1'),
|
||||
(@lastid, 136, ''),
|
||||
(@lastid, 137, ''),
|
||||
(@lastid, 138, ''),
|
||||
(@lastid, 139, '0'),
|
||||
(@lastid, 140, '0'),
|
||||
(@lastid, 96, ''),
|
||||
(@lastid, 97, ''),
|
||||
(@lastid, 98, '');
|
||||
|
||||
|
||||
|
|
|
@ -4,41 +4,47 @@
|
|||
;###################
|
||||
|
||||
; This value is used to detect quickly
|
||||
; if this config file is up to date
|
||||
; if this config file is up to date
|
||||
; this is compared against a value hard-coded
|
||||
; into the init script
|
||||
config_version = 16
|
||||
config_version = 29
|
||||
|
||||
;###################
|
||||
; Path Vars #
|
||||
;###################
|
||||
|
||||
; The http host of your server.
|
||||
; The public http host of your server.
|
||||
; If not set, retrieved automatically from client request.
|
||||
; This setting is required for WebSocket server
|
||||
; DEFAULT: ""
|
||||
http_host = "DOMAINTOCHANGE"
|
||||
|
||||
; The path to your ampache install
|
||||
; Do not put a trailing / on this path
|
||||
; The public path to your ampache install
|
||||
; Do not put a trailing / on this path
|
||||
; For example if your site is located at http://localhost
|
||||
; than you do not need to enter anything for the web_path
|
||||
; if it is located at http://localhost/music you need to
|
||||
; if it is located at http://localhost/music you need to
|
||||
; set web_path to /music
|
||||
; DEFAULT: ""
|
||||
web_path = "PATHTOCHANGE"
|
||||
|
||||
; The local http url of your server.
|
||||
; If not set, retrieved automatically from server information.
|
||||
; DEFAULT: ""
|
||||
;local_web_path = "http://localhost/ampache"
|
||||
|
||||
;##############################
|
||||
; Session and Login Variables #
|
||||
;##############################
|
||||
|
||||
; Hostname of your database
|
||||
; For socket authentication, set the path to socket file (e.g. /var/run/mysqld/mysqld.sock)
|
||||
; DEFAULT: localhost
|
||||
database_hostname = "localhost"
|
||||
|
||||
; Port to use when connecting to your database
|
||||
; DEFAULT: none
|
||||
;database_port = 3306
|
||||
database_port = ""
|
||||
|
||||
; Name of your ampache database
|
||||
; DEFAULT: ampache
|
||||
|
@ -50,44 +56,48 @@ database_username = "yunouser"
|
|||
|
||||
; Password for your ampache database, this can not be blank
|
||||
; this is a 'forced' security precaution, the default value
|
||||
; will not work
|
||||
; will not work (except if using socket authentication)
|
||||
; DEFAULT: ""
|
||||
database_password = "yunopass"
|
||||
|
||||
; Cryptographic secret
|
||||
; This MUST BE changed with your own secret key. Ampache-specific, just pick any random string you want.
|
||||
secret_key = "abcdefghijklmnoprqstuvwyz0123456"
|
||||
|
||||
; Length that a session will last expressed in seconds. Default is
|
||||
; one hour.
|
||||
; one hour.
|
||||
; DEFAULT: 3600
|
||||
session_length = "3600"
|
||||
session_length = 3600
|
||||
|
||||
; Length that the session for a single streaming instance will last
|
||||
; the default is two hours. With some clients, and long songs this can
|
||||
; the default is two hours. With some clients, and long songs this can
|
||||
; cause playback to stop, increase this value if you experience that
|
||||
; DEFAULT: 7200
|
||||
stream_length = "7200"
|
||||
stream_length = 7200
|
||||
|
||||
; This length defines how long a 'remember me' session and cookie will
|
||||
; last, the default is 7200, same as length. It is up to the administrator
|
||||
; of the box to increase this, for reference 86400 = 1 day
|
||||
; 604800 = 1 week and 2419200 = 1 month
|
||||
; DEFAULT: 86400
|
||||
remember_length = "86400"
|
||||
; This length defines how long a 'remember me' session and cookie will
|
||||
; last, the default is 86400, same as length. It is up to the administrator
|
||||
; of the box to increase this, for reference 86400 = 1 day,
|
||||
; 604800 = 1 week, and 2419200 = 1 month
|
||||
; DEFAULT: 604800
|
||||
remember_length = 604800
|
||||
|
||||
; Name of the Session/Cookie that will sent to the browser
|
||||
; default should be fine
|
||||
; DEFAULT: ampache
|
||||
session_name = "ampache"
|
||||
session_name = ampache
|
||||
|
||||
; Lifetime of the Cookie, 0 == Forever (until browser close) , otherwise in terms of seconds
|
||||
; If you want cookies to last past a browser close set this to a value in seconds.
|
||||
; If you want cookies to last past a browser close set this to a value in seconds.
|
||||
; DEFAULT: 0
|
||||
session_cookielife = "0"
|
||||
session_cookielife = 0
|
||||
|
||||
; Is the cookie a "secure" cookie? This should only be set to 1 (true) if you are
|
||||
; running a secure site (HTTPS).
|
||||
; running a secure site (HTTPS).
|
||||
; DEFAULT: 0
|
||||
session_cookiesecure = "1"
|
||||
session_cookiesecure = 0
|
||||
|
||||
; Auth Methods
|
||||
; Auth Methods
|
||||
; This defines which auth methods Auth will attempt to use and in which order.
|
||||
; If auto_create isn't enabled the user must exist locally.
|
||||
; DEFAULT: mysql
|
||||
|
@ -108,7 +118,7 @@ auth_methods = "http,mysql"
|
|||
;auth_password_save = "false"
|
||||
|
||||
; Logout redirection target
|
||||
; Defaults to our own login.php, but we can override it here if, for instance,
|
||||
; Defaults to our own login.php, but we can override it here if, for instance,
|
||||
; we want to redirect to an SSO provider instead.
|
||||
logout_redirect = "https://DOMAINTOCHANGE/yunohost/sso/?action=logout"
|
||||
|
||||
|
@ -120,15 +130,15 @@ logout_redirect = "https://DOMAINTOCHANGE/yunohost/sso/?action=logout"
|
|||
; This defines which file types Ampache will attempt to catalog
|
||||
; You can specify any file extension you want in here separating them
|
||||
; with a |
|
||||
; DEFAULT: mp3|mpc|m4p|m4a|mp4|aac|ogg|rm|wma|asf|flac|spx|ra|ape|shn|wv
|
||||
catalog_file_pattern = "mp3|mpc|m4p|m4a|mp4|aac|ogg|rm|wma|asf|flac|spx|ra|ape|shn|wv"
|
||||
; DEFAULT: mp3|mpc|m4p|m4a|aac|ogg|oga|wav|aif|aiff|rm|wma|asf|flac|opus|spx|ra|ape|shn|wv
|
||||
catalog_file_pattern = "mp3|mpc|m4p|m4a|aac|ogg|oga|wav|aif|aiff|rm|wma|asf|flac|opus|spx|ra|ape|shn|wv"
|
||||
|
||||
; Video Pattern
|
||||
; This defines which video file types Ampache will attempt to catalog
|
||||
; You can specify any file extension you want in here seperating them with
|
||||
; a | but ampache may not be able to parse them
|
||||
; DEAFULT: avi|mpg|flv|m4v|webm
|
||||
catalog_video_pattern = "avi|mpg|flv|m4v|webm"
|
||||
; DEAFULT: avi|mpg|mpeg|flv|m4v|mp4|webm|mkv|wmv|ogv|mov|divx|m2ts
|
||||
catalog_video_pattern = "avi|mpg|mpeg|flv|m4v|mp4|webm|mkv|wmv|ogv|mov|divx|m2ts"
|
||||
|
||||
; Playlist Pattern
|
||||
; This defines which playlist types Ampache will attempt to catalog
|
||||
|
@ -149,19 +159,19 @@ catalog_prefix_pattern = "The|An|A|Die|Das|Ein|Eine|Les|Le|La"
|
|||
; DEFAULT: false
|
||||
;catalog_disable = "false"
|
||||
|
||||
; Use Access List
|
||||
; Use Access List
|
||||
; Toggle this on if you want ampache to pay attention to the access list
|
||||
; and only allow streaming/downloading/api-rpc from known hosts api-rpc
|
||||
; and only allow streaming/downloading/api-rpc from known hosts api-rpc
|
||||
; will not work without this on.
|
||||
; NOTE: Default Behavior is DENY FROM ALL
|
||||
; NOTE: Default Behavior is DENY FROM ALL
|
||||
; DEFAULT: true
|
||||
access_control = "true"
|
||||
access_control = "true"
|
||||
|
||||
; Require Session
|
||||
; If this is set to true ampache will make sure that the URL passed when
|
||||
; attempting to retrieve a song contains a valid Session ID This prevents
|
||||
; others from guessing URL's. This setting is ignored if you have use_auth
|
||||
; disabled.
|
||||
; disabled.
|
||||
; DEFAULT: true
|
||||
require_session = "true"
|
||||
|
||||
|
@ -188,62 +198,63 @@ require_localnet_session = "true"
|
|||
|
||||
; Track User IPs
|
||||
; If this is enabled Ampache will log the IP of every completed login
|
||||
; it will store user,ip,time at one row per login. The results are
|
||||
; it will store user,ip,time at one row per login. The results are
|
||||
; displayed in Admin --> Users
|
||||
; DEFAULT: false
|
||||
;track_user_ip = "false"
|
||||
|
||||
; User IP Cardinality
|
||||
; This defines how many days worth of IP history Ampache will track
|
||||
; As it is one row per login on high volume sites you will want to
|
||||
; clear it every now and then.
|
||||
; As it is one row per login on high volume sites you will want to
|
||||
; clear it every now and then.
|
||||
; DEFAULT: 42 days
|
||||
;user_ip_cardinality = "42"
|
||||
|
||||
; Allow Zip Download
|
||||
; This setting allows/disallows using zlib to zip up an entire
|
||||
; playlist/album for download. Even if this is turned on you will
|
||||
; still need to enabled downloading for the specific user you
|
||||
; still need to enabled downloading for the specific user you
|
||||
; want to be able to use this function
|
||||
; DEFAULT: false
|
||||
;allow_zip_download = "false"
|
||||
|
||||
; File Zip Download
|
||||
; This settings tells Ampache to attempt to save the zip file
|
||||
; to the filesystem instead of creating it in memory, you must
|
||||
; also set tmp_dir_path in order for this to work
|
||||
; DEFAULT: false
|
||||
;file_zip_download = "false"
|
||||
Allow Zip Types
|
||||
; This setting allows/disallows zip download of specific object types
|
||||
; If empty, all supported object types can be zipped.
|
||||
; Otherwise, only the given object list can be zipped.
|
||||
; POSSIBLE VALUES: artist, album, playlist, search, tmp_playlist
|
||||
; DEFAULT: none
|
||||
;allow_zip_types = "album"
|
||||
|
||||
; File Zip Comment
|
||||
; This is an optional configuration option that adds a comment
|
||||
; to your zip files, this only applies if you've got allow_zip_downloads
|
||||
; DEFAULT: Ampache - Zip Batch Download
|
||||
;file_zip_comment = "Ampache - Zip Batch Download"
|
||||
;file_zip_comment = "Ampache - Zip Batch Download"
|
||||
|
||||
; Waveform
|
||||
; This settings tells Ampache to attempt to generate a waveform
|
||||
; for each song. It requires transcode and encode_args_wav settings.
|
||||
; You must also set tmp_dir_path in order for this to work
|
||||
; DEFAULT: false
|
||||
;waveform = "false"
|
||||
;waveform = "false"
|
||||
|
||||
; Waveform color
|
||||
; The waveform color.
|
||||
; DEFAULT: #FF0000
|
||||
;waveform_color = "#FF0000"
|
||||
;waveform_color = "#FF0000"
|
||||
|
||||
; Temporary Directory Path
|
||||
; If File Zip Download or Waveform is enabled this must be set to tell
|
||||
; If Waveform is enabled this must be set to tell
|
||||
; Ampache which directory to save the temporary file to. Do not put a
|
||||
; trailing slash or this will not work.
|
||||
; DEFAULT: false
|
||||
;tmp_dir_path = "false"
|
||||
|
||||
; This setting throttles a persons downloading to the specified
|
||||
; bytes per second. This is not a 100% guaranteed function, and
|
||||
; bytes per second. This is not a 100% guaranteed function, and
|
||||
; you should really use a server based rate limiter if you want
|
||||
; to do this correctly.
|
||||
; to do this correctly.
|
||||
; DEFAULT: off
|
||||
; VALUES: any whole number (in bytes per second)
|
||||
;throttle_download = 10
|
||||
|
@ -261,13 +272,52 @@ getid3_tag_order = "id3v2,id3v1,vorbiscomment,quicktime,matroska,ape,asf,avi,mpe
|
|||
; DEFAULT: false
|
||||
;getid3_detect_id3v2_encoding = "false"
|
||||
|
||||
; This determines if file metadata should be write back to files
|
||||
; as id3 metadata when updated.
|
||||
; DEFAULT: false
|
||||
;write_id3 = "false"
|
||||
|
||||
; This determines if album art should be write back to files
|
||||
; as id3 metadata when updated.
|
||||
; DEFAULT: false
|
||||
;write_id3_art = "false"
|
||||
|
||||
; This determines if catalog manager users can delete medias from disk.
|
||||
; DEFAULT: false
|
||||
;delete_from_disk = "false"
|
||||
|
||||
; This determines the order in which metadata sources are used (and in the
|
||||
; case of plugins, checked)
|
||||
; POSSIBLE VALUES (builtins): filename and getID3
|
||||
; POSSIBLE VALUES (plugins): MusicBrainz, plus any others you've installed.
|
||||
; POSSIBLE VALUES (plugins): MusicBrainz,TheAudioDb, plus any others you've installed.
|
||||
; DEFAULT: getID3 filename
|
||||
metadata_order = "getID3,filename"
|
||||
|
||||
; This determines the order in which metadata sources are used (and in the
|
||||
; case of plugins, checked) for video files
|
||||
; POSSIBLE VALUES (builtins): filename and getID3
|
||||
; POSSIBLE VALUES (plugins): Tvdb,Tmdb,Omdb, plus any others you've installed.
|
||||
; DEFAULT: filename getID3
|
||||
metadata_order_video = "filename,getID3"
|
||||
|
||||
; This determines if extended metadata grabbed from external services should be deferred.
|
||||
; If enabled, extended metadata is retrieved when browsing the library item.
|
||||
; If disabled, extended metadata is retrieved at catalog update.
|
||||
; Today, only Artist information (summary, place formed, ...) can be deferred.
|
||||
; DEFAULT: true
|
||||
deferred_ext_metadata = "true"
|
||||
|
||||
; Some taggers use delimiters other than \0 for fields
|
||||
; This list specifies possible delimiters additional to \0
|
||||
; This setting takes a regex pattern.
|
||||
; DEFAULT: // / \ | , ;
|
||||
additional_genre_delimiters = "[/]{2}|[/|\\\\|\|,|;]"
|
||||
|
||||
; This determines if a preview image should be retrieved from video files
|
||||
; It requires encode_get_image transcode settings.
|
||||
; DEFAULT: false
|
||||
;generate_video_preview = "true"
|
||||
|
||||
; Un comment if don't want ampache to follow symlinks
|
||||
; DEFAULT: false
|
||||
;no_symlinks = "false"
|
||||
|
@ -284,9 +334,9 @@ use_auth = "true"
|
|||
; If use_auth is set to false then this option is used
|
||||
; to determine the permission level of the 'default' users
|
||||
; default is administrator. This setting only takes affect
|
||||
; if use_auth if false
|
||||
; if use_auth is false
|
||||
; POSSIBLE VALUES: user, admin, manager, guest
|
||||
; DEFAULT: admin
|
||||
; DEFAULT: guest
|
||||
default_auth_level = "user"
|
||||
|
||||
; 5 Star Ratings
|
||||
|
@ -295,8 +345,8 @@ default_auth_level = "user"
|
|||
; DEFAULT: true
|
||||
ratings = "true"
|
||||
|
||||
; User flags
|
||||
; This allows user flags for almost any object in ampache
|
||||
; User flags/favorites
|
||||
; This allows user flags for almost any object in ampache as favorite
|
||||
; POSSIBLE VALUES: false true
|
||||
; DEFAULT: true
|
||||
userflags = "true"
|
||||
|
@ -310,14 +360,14 @@ directplay = "true"
|
|||
; Sociable
|
||||
; This turns on / off all of the "social" features of ampache
|
||||
; default is on, but if you don't care and just want music
|
||||
; turn this off to disable all social features.
|
||||
; turn this off to disable all social features.
|
||||
; DEFAULT: true
|
||||
sociable = "true"
|
||||
|
||||
; Notify
|
||||
; This turns on / off all Ampache notifications
|
||||
; DEFAULT: true
|
||||
notify = "true"
|
||||
; License
|
||||
; This turns on / off all licensing features on Ampache
|
||||
; DEFAULT: false
|
||||
licensing = "false"
|
||||
|
||||
; This options will turn on/off Demo Mode
|
||||
; If Demo mode is on you can not play songs or update your catalog
|
||||
|
@ -347,7 +397,43 @@ memory_cache = "true"
|
|||
; Especially useful if you have a front and a back image in a folder
|
||||
; comment out if ampache should search for any jpg,gif or png
|
||||
; DEFAULT: folder.jpg
|
||||
;album_art_preferred_filename = "folder.jpg"
|
||||
;album_art_preferred_filename = "folder.jpg"
|
||||
|
||||
; Album Art Store on Disk
|
||||
; This defines if arts should be stored on disk instead of database.
|
||||
; DEFAULT: false
|
||||
;album_art_store_disk = "false"
|
||||
|
||||
; Local Metadata Directory
|
||||
; This define a local metadata directory with write access where to store
|
||||
; heavy data if enabled (album arts, ...)
|
||||
; DEFAULT: none
|
||||
;local_metadata_dir = "/metadata"
|
||||
|
||||
; Maximal upload size
|
||||
; Specify the maximal allowed upload size for images, in bytes.
|
||||
; DEFAULT: 1048576
|
||||
;max_upload_size = 1048576
|
||||
|
||||
; Album Art Minimum Width
|
||||
; Specify the minimum width for arts (in pixel).
|
||||
; DEFAULT: none
|
||||
;album_art_min_width = 100
|
||||
|
||||
; Album Art Maximum Width
|
||||
; Specify the maximum width for arts (in pixel).
|
||||
; DEFAULT: none
|
||||
;album_art_max_width = 1024
|
||||
|
||||
; Album Art Minimum Height
|
||||
; Specify the minimum height for arts (in pixel).
|
||||
; DEFAULT: none
|
||||
;album_art_min_height = 100
|
||||
|
||||
; Album Art Maximum Height
|
||||
; Specify the maximum height for arts (in pixel).
|
||||
; DEFAULT: none
|
||||
;album_art_max_height = 1024
|
||||
|
||||
; Resize Images * Requires PHP-GD *
|
||||
; Set this to true if you want Ampache to resize the Album
|
||||
|
@ -357,24 +443,23 @@ memory_cache = "true"
|
|||
; DEFAULT: false
|
||||
;resize_images = "false"
|
||||
|
||||
; Statistical Graphs * Requires PHP-GD *
|
||||
; Set this to true if you want Ampache to generate statistical
|
||||
; graphs on usages / users.
|
||||
; DEFAULT: false
|
||||
;statistical_graphs = "false"
|
||||
|
||||
; Art Gather Order
|
||||
; Simply arrange the following in the order you would like
|
||||
; ampache to search. If you want to disable one of the search
|
||||
; methods simply leave it out. DB should be left as the first
|
||||
; method unless you want it to overwrite what's already in the
|
||||
; database
|
||||
; POSSIBLE VALUES: db tags folder amazon lastfm musicbrainz google
|
||||
; POSSIBLE VALUES (builtins): db tags folder lastfm musicbrainz google
|
||||
; POSSIBLE VALUES (plugins): Amazon,TheAudioDb,Tmdb,Omdb,Flickr
|
||||
; DEFAULT: db,tags,folder,musicbrainz,lastfm,google
|
||||
art_order = "db,tags,folder,musicbrainz,lastfm,google"
|
||||
|
||||
; Amazon Developer Key
|
||||
; These are needed in order to actually use the amazon album art
|
||||
; Your public key is your 'Access Key ID'
|
||||
; Your private key is your 'Secret Access Key'
|
||||
; DEFAULT: false
|
||||
;amazon_developer_public_key = ""
|
||||
;amazon_developer_private_key = ""
|
||||
|
||||
; Recommendations
|
||||
; Set this to true to enable display of similar artists or albums
|
||||
; while browsing. Requires Last.FM.
|
||||
|
@ -389,14 +474,14 @@ art_order = "db,tags,folder,musicbrainz,lastfm,google"
|
|||
|
||||
; Last.FM API Key
|
||||
; Set this to your Last.FM api key to actually use Last.FM for
|
||||
; recommendations.
|
||||
;lastfm_api_key = ""
|
||||
; recommendations and metadata.
|
||||
lastfm_api_key = "d5df942424c71b754e54ce1832505ae2"
|
||||
|
||||
; Wanted
|
||||
; Set this to true to enable display missing albums and the
|
||||
; possibility for users to mark it as wanted.
|
||||
; DEFAULT: false
|
||||
;wanted = "false"
|
||||
wanted = "true"
|
||||
|
||||
; Wanted types
|
||||
; Set the allowed types of wanted releases (album,compilation,single,ep,live,remix,promotion,official)
|
||||
|
@ -412,59 +497,50 @@ wanted_types = "album,official"
|
|||
; EchoNest provides several music services. Currently used for missing song 30 seconds preview.
|
||||
;echonest_api_key = ""
|
||||
|
||||
; Labels
|
||||
; Use labels to browse artists per label membership.
|
||||
; DEFAULT: false
|
||||
;label = "false"
|
||||
|
||||
; Broadcasts
|
||||
; Allow users to broadcast music.
|
||||
; This feature requires advanced server configuration, please take a look on the wiki for more information.
|
||||
; DEFAULT: false
|
||||
;broadcast = "false"
|
||||
|
||||
; Channels
|
||||
; Set this to true to enable channels and the
|
||||
; possibility for users to create channels from playlists
|
||||
; DEFAULT: true
|
||||
channel = "true"
|
||||
|
||||
; Live Streams
|
||||
; Set this to true to enable live streams (radio) and the
|
||||
; possibility for users to add new live streams.
|
||||
; DEFAULT: true
|
||||
live_stream = "true"
|
||||
|
||||
; Web Socket address
|
||||
; Declare the web socket server address
|
||||
; DEFAULT: determined automatically
|
||||
;websocket_address = "ws://localhost:8100"
|
||||
|
||||
; Amazon base urls
|
||||
; An array of Amazon sites to search.
|
||||
; NOTE: This will search each of these sites in turn so don't expect it
|
||||
; to be lightning fast!
|
||||
; It is strongly recommended that only one of these is selected at any
|
||||
; one time
|
||||
; POSSIBLE VALUES:
|
||||
; http://webservices.amazon.com
|
||||
; http://webservices.amazon.co.uk
|
||||
; http://webservices.amazon.de
|
||||
; http://webservices.amazon.co.jp
|
||||
; http://webservices.amazon.fr
|
||||
; http://webservices.amazon.ca
|
||||
; Default: http://webservices.amazon.com
|
||||
;amazon_base_urls = "http://webservices.amazon.com"
|
||||
|
||||
; max_amazon_results_pages
|
||||
; The maximum number of results pages to pull from EACH amazon site
|
||||
; NOTE: The art search pages through the results returned by your search
|
||||
; up to this number of pages. As with the base_urls above, this is going
|
||||
; to take more time, the more pages you ask it to process.
|
||||
; Of course a good search will return only a few matches anyway.
|
||||
; It is strongly recommended that you do _not_ change this value
|
||||
; DEFAULT: 1 page (10 items)
|
||||
max_amazon_results_pages = "1"
|
||||
|
||||
; Debug
|
||||
; If this is enabled Ampache will write debugging information to the log file
|
||||
; DEFAULT: false
|
||||
debug = "true"
|
||||
;debug = "false"
|
||||
|
||||
; Debug Level
|
||||
; This should always be set in conjunction with the
|
||||
; debug option, it defines how prolific you want the
|
||||
; debugging in ampache to be. values are 1-5.
|
||||
; debugging in ampache to be. values are 1-5.
|
||||
; 1 == Errors only
|
||||
; 2 == Error + Failures (login attempts etc.)
|
||||
; 3 == ??
|
||||
; 4 == ?? (Profit!)
|
||||
; 5 == Information (cataloging progress etc.)
|
||||
; DEFAULT: 5
|
||||
debug_level = "5"
|
||||
debug_level = 5
|
||||
|
||||
; Path to Log File
|
||||
; This defines where you want ampache to log events to
|
||||
|
@ -486,22 +562,28 @@ log_filename = "%name.%Y%m%d.log"
|
|||
; DEFAULT: UTF-8
|
||||
site_charset = "UTF-8"
|
||||
|
||||
; Locale Charset
|
||||
; In some cases this has to be different
|
||||
; in order for XHTML and other things to work
|
||||
; This is disabled by default, enabled only
|
||||
; if needed. It's specifically needed for Russian
|
||||
; so that is the default
|
||||
; DEFAULT: cp1251
|
||||
;lc_charset = cp1251
|
||||
; Locale Charset
|
||||
; Local charset (mainly for file operations) if different
|
||||
; from site_charset.
|
||||
; This is disabled by default, enable only if needed
|
||||
; (for Windows please set lc_charset to ISO8859-1)
|
||||
; DEFAULT: ISO8859-1
|
||||
;lc_charset = "ISO8859-1"
|
||||
|
||||
; Refresh Limit
|
||||
; This defines the default refresh limit in seconds for
|
||||
; This defines the default refresh limit in seconds for
|
||||
; pages with dynamic content, such as now playing
|
||||
; DEFAULT: 60
|
||||
; Possible Values: Int > 5
|
||||
refresh_limit = "60"
|
||||
|
||||
; Footer Statistics
|
||||
; This defines whether statistics (Queries, Cache Hits, Load Time)
|
||||
; are shown in the page footer.
|
||||
; DEFAULT: true
|
||||
; Possible values: true, false
|
||||
show_footer_statistics = "true"
|
||||
|
||||
;#########################################################
|
||||
; Custom actions (optional) #
|
||||
;#########################################################
|
||||
|
@ -528,10 +610,10 @@ refresh_limit = "60"
|
|||
;#########################################################
|
||||
|
||||
; LDAP filter string to use (required)
|
||||
; For OpenLDAP use "uid"
|
||||
; For OpenLDAP use "uid"
|
||||
; For Microsoft Active Directory (MAD) use "sAMAccountName"
|
||||
; DEFAULT: null
|
||||
; ldap_filter = "sAMAccountName"
|
||||
;ldap_filter = "(sAMAccountName=%v)"
|
||||
|
||||
; LDAP objectclass (required)
|
||||
; OpanLDAP objectclass = "*"
|
||||
|
@ -561,7 +643,7 @@ ldap_url = "localhost"
|
|||
; MAD ldap_name_field = "displayname"
|
||||
; DEFAULT: null
|
||||
;ldap_email_field = "mail"
|
||||
ldap_name_field = "cn"
|
||||
ldap_name_field = "cn"
|
||||
|
||||
;#########################################################
|
||||
; OpenID login info (optional) #
|
||||
|
@ -608,19 +690,41 @@ auto_create = "true"
|
|||
; DEFAULT: false
|
||||
;admin_enable_required = "false"
|
||||
|
||||
; This setting will allow all registrants/ldap/http users
|
||||
; to be auto-approved as a user. By default, they will be
|
||||
; This setting will allow all registrants/ldap/http users
|
||||
; to be auto-approved as a user. By default, they will be
|
||||
; added as a guest and must be promoted by the admin.
|
||||
; POSSIBLE VALUES: guest, user, admin
|
||||
; DEFAULT: guest
|
||||
auto_user = "user"
|
||||
|
||||
; This will display the user agreement when registering
|
||||
; For agreement text, edit templates/user_agreement.php
|
||||
; For agreement text, edit config/registration_agreement.php
|
||||
; User will need to accept the agreement before they can register
|
||||
; DEFAULT: false
|
||||
;user_agreement = "false"
|
||||
|
||||
; This disable email confirmation when registering.
|
||||
; DEFAULT: false
|
||||
;user_no_email_confirm = "false"
|
||||
|
||||
; This will display the cookie disclaimer (EU Cookie Law)
|
||||
; DEFAULT: false
|
||||
cookie_disclaimer = "false"
|
||||
|
||||
; The fields that will be shown on Registration page
|
||||
; If a user wants to register.
|
||||
; Username and email fields are forced.
|
||||
; POSSIBLE VALUES: fullname,website,state,city
|
||||
; DEFAULT: "fullname,website"
|
||||
registration_display_fields = "fullname,website"
|
||||
|
||||
; The fields that will be mandatory
|
||||
; This controls which fields are mandatory for registration.
|
||||
; Username and email fields are forced mandatory.
|
||||
; POSSIBLE VALUES: fullname,website,state,city
|
||||
; DEFAULT: fullname
|
||||
registration_mandatory_fields = "fullname"
|
||||
|
||||
;########################################################
|
||||
; These options control the dynamic downsampling based #
|
||||
; on current usage #
|
||||
|
@ -638,11 +742,11 @@ max_bit_rate = 576
|
|||
; New dynamically downsampled streams will be denied if they are forced below
|
||||
; this value.
|
||||
; DEFAULT: 8
|
||||
min_bit_rate = 48
|
||||
;min_bit_rate = 48
|
||||
|
||||
;######################################################
|
||||
; These are commands used to transcode non-streaming
|
||||
; formats to the target file type for streaming.
|
||||
; formats to the target file type for streaming.
|
||||
; This can be useful in re-encoding file types that don't stream
|
||||
; very well, or if your player doesn't support some file types.
|
||||
;
|
||||
|
@ -658,23 +762,64 @@ min_bit_rate = 48
|
|||
; (e.g. if you store everything in FLAC, but don't want to ever stream that.)
|
||||
; transcode_TYPE = {allowed|required|false}
|
||||
; DEFAULT: false
|
||||
;;; Audio
|
||||
;transcode_m4a = allowed
|
||||
transcode_flac = required
|
||||
;transcode_mpc = required
|
||||
;transcode_ogg = required
|
||||
;transcode_oga = required
|
||||
;transcode_wav = required
|
||||
;transcode_wma = required
|
||||
;transcode_aif = required
|
||||
;transcode_aiff = required
|
||||
;transcode_ape = required
|
||||
;transcode_shn = required
|
||||
transcode_mp3 = allowed
|
||||
;;; Video
|
||||
;transcode_avi = allowed
|
||||
;transcode_mkv = allowed
|
||||
;transcode_mpg = allowed
|
||||
;transcode_mpeg = allowed
|
||||
;transcode_m4v = allowed
|
||||
;transcode_mp4 = allowed
|
||||
;transcode_mov = allowed
|
||||
;transcode_wmv = allowed
|
||||
;transcode_ogv = allowed
|
||||
;transcode_divx = allowed
|
||||
;transcode_m2ts = allowed
|
||||
;transcode_webm = allowed
|
||||
|
||||
; Default output format
|
||||
; Default audio output format
|
||||
; DEFAULT: none
|
||||
encode_target = mp3
|
||||
|
||||
; Default video output format
|
||||
; DEFAULT: none
|
||||
;encode_video_target = webm
|
||||
|
||||
; Override the default output format on a per-type basis
|
||||
; encode_target_TYPE = TYPE
|
||||
; DEFAULT: none
|
||||
; encode_target_flac = ogg
|
||||
;encode_target_flac = ogg
|
||||
|
||||
; Override the default TYPE transcoding behavior on a per-player basis
|
||||
; transcode_player_PLAYER_TYPE = TYPE
|
||||
; Valid PLAYER is: webplayer, api
|
||||
; DEFAULT: none
|
||||
;transcode_player_webplayer_m4a = required
|
||||
;transcode_player_webplayer_flac = required
|
||||
;transcode_player_webplayer_mpc = required
|
||||
|
||||
; Override the default output format on a per-player basis
|
||||
; encode_player_PLAYER_target = TYPE
|
||||
; Valid PLAYER is: webplayer, api
|
||||
; DEFAULT: none
|
||||
;encode_player_webplayer_target = mp3
|
||||
;encode_player_api_target = mp3
|
||||
|
||||
; Allow clients to override transcode settings (output type, bitrate, codec ...)
|
||||
; DEFAULT: true
|
||||
transcode_player_customize = "1"
|
||||
transcode_player_customize = "true"
|
||||
|
||||
; Command configuration. Substitutions will be made as follows:
|
||||
; %FILE% => filename
|
||||
|
@ -688,30 +833,45 @@ transcode_player_customize = "1"
|
|||
; equivalent to the old default, but if you find that necessary you should be
|
||||
; clever enough to figure out how on your own.
|
||||
; DEFAULT: none
|
||||
;transcode_cmd = "ffmpeg -i %FILE%"
|
||||
transcode_cmd = "ffmpeg -i %FILE%"
|
||||
;transcode_cmd = "/usr/bin/neatokeen %FILE%"
|
||||
;transcode_cmd = "ffmpeg"
|
||||
transcode_cmd = "avconv"
|
||||
;transcode_cmd = "/usr/bin/neatokeen"
|
||||
|
||||
; Transcode input file argument
|
||||
transcode_input = "-i %FILE%"
|
||||
|
||||
; Specific transcode commands
|
||||
; It shouldn't be necessary in most cases, but you can override the transcode
|
||||
; command for specific source formats. It still needs to accept the
|
||||
; command for specific source formats. It still needs to accept the
|
||||
; encoding arguments, so the easiest approach is to use your normal command as
|
||||
; a clearing-house.
|
||||
; transcode_cmd_TYPE = TRANSCODE_CMD
|
||||
;transcode_cmd_mid = "timidity -Or -o – %FILE% | ffmpeg -f s16le -i pipe:0"
|
||||
;transcode_cmd_mid = "timidity -Or -o – %FILE% | ffmpeg -f s16le -i pipe:0"
|
||||
|
||||
; Encoding arguments
|
||||
; For each output format, you should provide the necessary arguments for
|
||||
; your transcode_cmd.
|
||||
; your transcode_cmd.
|
||||
; encode_args_TYPE = TRANSCODE_CMD_ARGS
|
||||
;encode_args_mp3 = "-vn -b:a %SAMPLE%K -c:a libmp3lame -f mp3 pipe:1"
|
||||
;encode_args_ogg = "-vn -b:a %SAMPLE%K -c:a libvorbis -f ogg pipe:1"
|
||||
;encode_args_m4a = "-vn -b:a %SAMPLE%K -c:a libfdk_aac -f adts pipe:1"
|
||||
;encode_args_wav = "-vn -b:a %SAMPLE%K -c:a pcm_s16le -f wav pipe:1"
|
||||
encode_args_ogg = "-vn -b:a max\(%SAMPLE%K\,49K\) -acodec libvorbis -vcodec libtheora -f ogg pipe:1"
|
||||
encode_args_mp3 = "-vn -b:a %SAMPLE%K -acodec libmp3lame -f mp3 pipe:1"
|
||||
encode_args_ogv = "-vcodec libtheora -acodec libvorbis -ar 44100 -f ogv pipe:1"
|
||||
encode_args_mp4 = "-profile:0 baseline -frag_duration 2 -ar 44100 -f mp4 pipe:1"
|
||||
encode_args_mp3 = "-vn -b:a %SAMPLE%K -c:a libmp3lame -f mp3 pipe:1"
|
||||
encode_args_ogg = "-vn -b:a %SAMPLE%K -c:a libvorbis -f ogg pipe:1"
|
||||
encode_args_m4a = "-vn -b:a %SAMPLE%K -c:a libfdk_aac -f adts pipe:1"
|
||||
encode_args_wav = "-vn -b:a %SAMPLE%K -c:a pcm_s16le -f wav pipe:1"
|
||||
encode_args_flv = "-b:a %SAMPLE%K -ar 44100 -ac 2 -v 0 -f flv -c:v libx264 -preset superfast -threads 0 pipe:1"
|
||||
encode_args_webm = "-q %QUALITY% -f webm -c:v libvpx -maxrate %MAXBITRATE%k -preset superfast -threads 0 pipe:1"
|
||||
encode_args_ts = "-q %QUALITY% -s %RESOLUTION% -f mpegts -c:v libx264 -c:a libmp3lame -maxrate %MAXBITRATE%k -preset superfast -threads 0 pipe:1"
|
||||
|
||||
; Encoding arguments to retrieve an image from a single frame
|
||||
encode_get_image = "-ss %TIME% -f image2 -vframes 1 pipe:1"
|
||||
|
||||
; Encoding argument to encrust subtitle
|
||||
encode_srt = "-vf \"subtitles='%SRTFILE%'\""
|
||||
|
||||
; Encode segment frame argument
|
||||
encode_ss_frame = "-ss %TIME%"
|
||||
|
||||
; Encode segment duration argument
|
||||
encode_ss_duration = "-t %DURATION%"
|
||||
|
||||
|
||||
;######################################################
|
||||
; these options allow you to configure your rss-feed
|
||||
|
@ -719,7 +879,7 @@ encode_args_mp4 = "-profile:0 baseline -frag_duration 2 -ar 44100 -f mp4 pipe:1"
|
|||
; song is the information in the feed. can be multiple items.
|
||||
; use_rss = false (values true | false)
|
||||
;DEFAULT: use_rss = false
|
||||
;use_rss = false
|
||||
;use_rss = "false"
|
||||
;#####################################################
|
||||
|
||||
;#############################
|
||||
|
@ -735,7 +895,7 @@ encode_args_mp4 = "-profile:0 baseline -frag_duration 2 -ar 44100 -f mp4 pipe:1"
|
|||
|
||||
; If Ampache is behind an https reverse proxy, force use HTTPS protocol.
|
||||
;Default: false
|
||||
force_ssl = true
|
||||
force_ssl = "true"
|
||||
|
||||
;#############################
|
||||
; Mail Settings #
|
||||
|
@ -747,7 +907,7 @@ force_ssl = true
|
|||
;mail_type = "php"
|
||||
|
||||
;Mail domain.
|
||||
;DEFAULT: example.com
|
||||
;DEFAULT: example.com
|
||||
;mail_domain = "example.com"
|
||||
|
||||
;This will be combined with mail_domain and used as the source address for
|
||||
|
@ -794,7 +954,7 @@ force_ssl = true
|
|||
|
||||
;Enable SMTP authentication
|
||||
;DEFAULT: false
|
||||
;mail_auth = true
|
||||
;mail_auth = "true"
|
||||
|
||||
;SMTP Username
|
||||
;your mail auth username.
|
||||
|
|
977
conf/ampache.cfg.php.old
Normal file
|
@ -0,0 +1,977 @@
|
|||
;#<?php exit(); ?>##
|
||||
;###################
|
||||
; General Config #
|
||||
;###################
|
||||
|
||||
; This value is used to detect quickly
|
||||
; if this config file is up to date
|
||||
; this is compared against a value hard-coded
|
||||
; into the init script
|
||||
config_version = 29
|
||||
|
||||
;###################
|
||||
; Path Vars #
|
||||
;###################
|
||||
|
||||
; The public http host of your server.
|
||||
; If not set, retrieved automatically from client request.
|
||||
; This setting is required for WebSocket server
|
||||
; DEFAULT: ""
|
||||
http_host = "DOMAINTOCHANGE"
|
||||
|
||||
; The public path to your ampache install
|
||||
; Do not put a trailing / on this path
|
||||
; For example if your site is located at http://localhost
|
||||
; than you do not need to enter anything for the web_path
|
||||
; if it is located at http://localhost/music you need to
|
||||
; set web_path to /music
|
||||
; DEFAULT: ""
|
||||
web_path = "PATHTOCHANGE"
|
||||
|
||||
; The local http url of your server.
|
||||
; If not set, retrieved automatically from server information.
|
||||
; DEFAULT: ""
|
||||
;local_web_path = "http://localhost/ampache"
|
||||
|
||||
;##############################
|
||||
; Session and Login Variables #
|
||||
;##############################
|
||||
|
||||
; Hostname of your database
|
||||
; For socket authentication, set the path to socket file (e.g. /var/run/mysqld/mysqld.sock)
|
||||
; DEFAULT: localhost
|
||||
database_hostname = "localhost"
|
||||
|
||||
; Port to use when connecting to your database
|
||||
; DEFAULT: none
|
||||
;database_port = 3306
|
||||
|
||||
; Name of your ampache database
|
||||
; DEFAULT: ampache
|
||||
database_name = "yunobase"
|
||||
|
||||
; Username for your ampache database
|
||||
; DEFAULT: ""
|
||||
database_username = "yunouser"
|
||||
|
||||
; Password for your ampache database, this can not be blank
|
||||
; this is a 'forced' security precaution, the default value
|
||||
; will not work (except if using socket authentication)
|
||||
; DEFAULT: ""
|
||||
database_password = "yunopass"
|
||||
|
||||
; Cryptographic secret
|
||||
; This MUST BE changed with your own secret key. Ampache-specific, just pick any random string you want.
|
||||
secret_key = "abcdefghijklmnoprqstuvwyz0123456"
|
||||
|
||||
; Length that a session will last expressed in seconds. Default is
|
||||
; one hour.
|
||||
; DEFAULT: 3600
|
||||
session_length = "3600"
|
||||
|
||||
; Length that the session for a single streaming instance will last
|
||||
; the default is two hours. With some clients, and long songs this can
|
||||
; cause playback to stop, increase this value if you experience that
|
||||
; DEFAULT: 7200
|
||||
stream_length = "7200"
|
||||
|
||||
; This length defines how long a 'remember me' session and cookie will
|
||||
; last, the default is 86400, same as length. It is up to the administrator
|
||||
; of the box to increase this, for reference 86400 = 1 day,
|
||||
; 604800 = 1 week, and 2419200 = 1 month
|
||||
; DEFAULT: 604800
|
||||
remember_length = "86400"
|
||||
|
||||
; Name of the Session/Cookie that will sent to the browser
|
||||
; default should be fine
|
||||
; DEFAULT: ampache
|
||||
session_name = "ampache"
|
||||
|
||||
; Lifetime of the Cookie, 0 == Forever (until browser close) , otherwise in terms of seconds
|
||||
; If you want cookies to last past a browser close set this to a value in seconds.
|
||||
; DEFAULT: 0
|
||||
session_cookielife = "0"
|
||||
|
||||
; Is the cookie a "secure" cookie? This should only be set to 1 (true) if you are
|
||||
; running a secure site (HTTPS).
|
||||
; DEFAULT: 0
|
||||
session_cookiesecure = "1"
|
||||
|
||||
; Auth Methods
|
||||
; This defines which auth methods Auth will attempt to use and in which order.
|
||||
; If auto_create isn't enabled the user must exist locally.
|
||||
; DEFAULT: mysql
|
||||
; VALUES: mysql,ldap,http,pam,external,openid
|
||||
auth_methods = "http,mysql"
|
||||
|
||||
; External authentication
|
||||
; This sets the helper used for external authentication. It should conform to
|
||||
; the interface used by mod_authnz_external
|
||||
; DEFAULT: none
|
||||
;external_authenticator = "/usr/sbin/pwauth"
|
||||
|
||||
; Automatic local password updating
|
||||
; Determines whether successful authentication against an external source
|
||||
; will result in an update to the password stored in the database.
|
||||
; A locally stored password is needed for API access.
|
||||
; DEFAULT: false
|
||||
;auth_password_save = "false"
|
||||
|
||||
; Logout redirection target
|
||||
; Defaults to our own login.php, but we can override it here if, for instance,
|
||||
; we want to redirect to an SSO provider instead.
|
||||
logout_redirect = "https://DOMAINTOCHANGE/yunohost/sso/?action=logout"
|
||||
|
||||
;#####################
|
||||
; Program Settings #
|
||||
;#####################
|
||||
|
||||
; File Pattern
|
||||
; This defines which file types Ampache will attempt to catalog
|
||||
; You can specify any file extension you want in here separating them
|
||||
; with a |
|
||||
; DEFAULT: mp3|mpc|m4p|m4a|aac|ogg|oga|wav|aif|aiff|rm|wma|asf|flac|opus|spx|ra|ape|shn|wv
|
||||
catalog_file_pattern = "mp3|mpc|m4p|m4a|mp4|aac|ogg|rm|wma|asf|flac|spx|ra|ape|shn|wv"
|
||||
|
||||
; Video Pattern
|
||||
; This defines which video file types Ampache will attempt to catalog
|
||||
; You can specify any file extension you want in here seperating them with
|
||||
; a | but ampache may not be able to parse them
|
||||
; DEAFULT: avi|mpg|mpeg|flv|m4v|mp4|webm|mkv|wmv|ogv|mov|divx|m2ts
|
||||
catalog_video_pattern = "avi|mpg|flv|m4v|webm"
|
||||
|
||||
; Playlist Pattern
|
||||
; This defines which playlist types Ampache will attempt to catalog
|
||||
; You can specify any file extension you want in here seperating them with
|
||||
; a | but ampache may not be able to parse them
|
||||
; DEFAULT: m3u|pls|asx|xspf
|
||||
catalog_playlist_pattern = "m3u|pls|asx|xspf"
|
||||
|
||||
; Prefix Pattern
|
||||
; This defines which prefix Ampache will ignore when importing tags from
|
||||
; your music. You may add any prefix you want seperating them with a |
|
||||
; DEFAULT: The|An|A|Die|Das|Ein|Eine|Les|Le|La
|
||||
catalog_prefix_pattern = "The|An|A|Die|Das|Ein|Eine|Les|Le|La"
|
||||
|
||||
; Catalog disable
|
||||
; This defines if catalog can be disabled without removing database entries
|
||||
; WARNING: this increase sensibly sql requests and slow down Ampache a lot
|
||||
; DEFAULT: false
|
||||
;catalog_disable = "false"
|
||||
|
||||
; Use Access List
|
||||
; Toggle this on if you want ampache to pay attention to the access list
|
||||
; and only allow streaming/downloading/api-rpc from known hosts api-rpc
|
||||
; will not work without this on.
|
||||
; NOTE: Default Behavior is DENY FROM ALL
|
||||
; DEFAULT: true
|
||||
access_control = "true"
|
||||
|
||||
; Require Session
|
||||
; If this is set to true ampache will make sure that the URL passed when
|
||||
; attempting to retrieve a song contains a valid Session ID This prevents
|
||||
; others from guessing URL's. This setting is ignored if you have use_auth
|
||||
; disabled.
|
||||
; DEFAULT: true
|
||||
require_session = "true"
|
||||
|
||||
; Require LocalNet Session
|
||||
; If this is set to true then ampache will require that a valid session
|
||||
; is passed even on hosts defined in the Local Network ACL. This setting
|
||||
; has no effect if access_control is not enabled
|
||||
; DEFAULT: true
|
||||
require_localnet_session = "true"
|
||||
|
||||
; Multiple Logins
|
||||
; Added by Vlet 07/25/07
|
||||
; When this setting is enabled a user may only be logged in from a single
|
||||
; IP address at any one time, this is to prevent sharing of accounts
|
||||
; DEFAULT: false
|
||||
;prevent_multiple_logins = "false"
|
||||
|
||||
; Downsample Remote
|
||||
; If this is set to true and access control is on any users who are not
|
||||
; coming from a defined 'network' ACL will be automatically downsampled
|
||||
; regardless of their preferences. Requires access_control to be enabled
|
||||
; DEFAULT: false
|
||||
;downsample_remote = "false"
|
||||
|
||||
; Track User IPs
|
||||
; If this is enabled Ampache will log the IP of every completed login
|
||||
; it will store user,ip,time at one row per login. The results are
|
||||
; displayed in Admin --> Users
|
||||
; DEFAULT: false
|
||||
;track_user_ip = "false"
|
||||
|
||||
; User IP Cardinality
|
||||
; This defines how many days worth of IP history Ampache will track
|
||||
; As it is one row per login on high volume sites you will want to
|
||||
; clear it every now and then.
|
||||
; DEFAULT: 42 days
|
||||
;user_ip_cardinality = "42"
|
||||
|
||||
; Allow Zip Download
|
||||
; This setting allows/disallows using zlib to zip up an entire
|
||||
; playlist/album for download. Even if this is turned on you will
|
||||
; still need to enabled downloading for the specific user you
|
||||
; want to be able to use this function
|
||||
; DEFAULT: false
|
||||
;allow_zip_download = "false"
|
||||
|
||||
Allow Zip Types
|
||||
; This setting allows/disallows zip download of specific object types
|
||||
; If empty, all supported object types can be zipped.
|
||||
; Otherwise, only the given object list can be zipped.
|
||||
; POSSIBLE VALUES: artist, album, playlist, search, tmp_playlist
|
||||
; DEFAULT: none
|
||||
;allow_zip_types = "album"
|
||||
|
||||
; File Zip Comment
|
||||
; This is an optional configuration option that adds a comment
|
||||
; to your zip files, this only applies if you've got allow_zip_downloads
|
||||
; DEFAULT: Ampache - Zip Batch Download
|
||||
;file_zip_comment = "Ampache - Zip Batch Download"
|
||||
|
||||
; Waveform
|
||||
; This settings tells Ampache to attempt to generate a waveform
|
||||
; for each song. It requires transcode and encode_args_wav settings.
|
||||
; You must also set tmp_dir_path in order for this to work
|
||||
; DEFAULT: false
|
||||
;waveform = "false"
|
||||
|
||||
; Waveform color
|
||||
; The waveform color.
|
||||
; DEFAULT: #FF0000
|
||||
;waveform_color = "#FF0000"
|
||||
|
||||
; Temporary Directory Path
|
||||
; If Waveform is enabled this must be set to tell
|
||||
; Ampache which directory to save the temporary file to. Do not put a
|
||||
; trailing slash or this will not work.
|
||||
; DEFAULT: false
|
||||
;tmp_dir_path = "false"
|
||||
|
||||
; This setting throttles a persons downloading to the specified
|
||||
; bytes per second. This is not a 100% guaranteed function, and
|
||||
; you should really use a server based rate limiter if you want
|
||||
; to do this correctly.
|
||||
; DEFAULT: off
|
||||
; VALUES: any whole number (in bytes per second)
|
||||
;throttle_download = 10
|
||||
|
||||
; This determines the tag order for all cataloged
|
||||
; music. If none of the listed tags are found then
|
||||
; ampache will randomly use whatever was found.
|
||||
; POSSIBLE VALUES: ape asf avi id3v1 id3v2 lyrics3 matroska mpeg quicktime riff
|
||||
; vorbiscomment
|
||||
; DEFAULT: id3v2 id3v1 vorbiscomment quicktime matroska ape asf avi mpeg riff
|
||||
getid3_tag_order = "id3v2,id3v1,vorbiscomment,quicktime,matroska,ape,asf,avi,mpeg,riff"
|
||||
|
||||
; Determines whether we try to autodetect the encoding for id3v2 tags.
|
||||
; May break valid tags.
|
||||
; DEFAULT: false
|
||||
;getid3_detect_id3v2_encoding = "false"
|
||||
|
||||
; This determines if file metadata should be write back to files
|
||||
; as id3 metadata when updated.
|
||||
; DEFAULT: false
|
||||
;write_id3 = "false"
|
||||
|
||||
; This determines if album art should be write back to files
|
||||
; as id3 metadata when updated.
|
||||
; DEFAULT: false
|
||||
;write_id3_art = "false"
|
||||
|
||||
; This determines if catalog manager users can delete medias from disk.
|
||||
; DEFAULT: false
|
||||
;delete_from_disk = "false"
|
||||
|
||||
; This determines the order in which metadata sources are used (and in the
|
||||
; case of plugins, checked)
|
||||
; POSSIBLE VALUES (builtins): filename and getID3
|
||||
; POSSIBLE VALUES (plugins): MusicBrainz,TheAudioDb, plus any others you've installed.
|
||||
; DEFAULT: getID3 filename
|
||||
metadata_order = "getID3,filename"
|
||||
|
||||
; This determines the order in which metadata sources are used (and in the
|
||||
; case of plugins, checked) for video files
|
||||
; POSSIBLE VALUES (builtins): filename and getID3
|
||||
; POSSIBLE VALUES (plugins): Tvdb,Tmdb,Omdb, plus any others you've installed.
|
||||
; DEFAULT: filename getID3
|
||||
metadata_order_video = "filename,getID3"
|
||||
|
||||
; This determines if extended metadata grabbed from external services should be deferred.
|
||||
; If enabled, extended metadata is retrieved when browsing the library item.
|
||||
; If disabled, extended metadata is retrieved at catalog update.
|
||||
; Today, only Artist information (summary, place formed, ...) can be deferred.
|
||||
; DEFAULT: true
|
||||
deferred_ext_metadata = "true"
|
||||
|
||||
; Some taggers use delimiters other than \0 for fields
|
||||
; This list specifies possible delimiters additional to \0
|
||||
; This setting takes a regex pattern.
|
||||
; DEFAULT: // / \ | , ;
|
||||
additional_genre_delimiters = "[/]{2}|[/|\\\\|\|,|;]"
|
||||
|
||||
; This determines if a preview image should be retrieved from video files
|
||||
; It requires encode_get_image transcode settings.
|
||||
; DEFAULT: false
|
||||
;generate_video_preview = "true"
|
||||
|
||||
; Un comment if don't want ampache to follow symlinks
|
||||
; DEFAULT: false
|
||||
;no_symlinks = "false"
|
||||
|
||||
; Use auth?
|
||||
; If this is set to "Yes" ampache will require a valid
|
||||
; Username and password. If this is set to false then ampache
|
||||
; will not ask you for a username and password. false is only
|
||||
; recommended for internal only instances
|
||||
; DEFAULT true
|
||||
use_auth = "true"
|
||||
|
||||
; Default Auth Level
|
||||
; If use_auth is set to false then this option is used
|
||||
; to determine the permission level of the 'default' users
|
||||
; default is administrator. This setting only takes affect
|
||||
; if use_auth is false
|
||||
; POSSIBLE VALUES: user, admin, manager, guest
|
||||
; DEFAULT: guest
|
||||
default_auth_level = "user"
|
||||
|
||||
; 5 Star Ratings
|
||||
; This allows ratings for almost any object in ampache
|
||||
; POSSIBLE VALUES: false true
|
||||
; DEFAULT: true
|
||||
ratings = "true"
|
||||
|
||||
; User flags/favorites
|
||||
; This allows user flags for almost any object in ampache as favorite
|
||||
; POSSIBLE VALUES: false true
|
||||
; DEFAULT: true
|
||||
userflags = "true"
|
||||
|
||||
; Direct play
|
||||
; This allows user to play directly a song or album
|
||||
; POSSIBLE VALUES: false true
|
||||
; DEFAULT: true
|
||||
directplay = "true"
|
||||
|
||||
; Sociable
|
||||
; This turns on / off all of the "social" features of ampache
|
||||
; default is on, but if you don't care and just want music
|
||||
; turn this off to disable all social features.
|
||||
; DEFAULT: true
|
||||
sociable = "true"
|
||||
|
||||
; License
|
||||
; This turns on / off all licensing features on Ampache
|
||||
; DEFAULT: false
|
||||
;licensing = "false"
|
||||
|
||||
; This options will turn on/off Demo Mode
|
||||
; If Demo mode is on you can not play songs or update your catalog
|
||||
; in other words.. leave this commented out
|
||||
; DEFAULT: false
|
||||
;demo_mode = "false"
|
||||
|
||||
; Caching
|
||||
; This turns the caching mechanisms on or off, due to a large number of
|
||||
; problems with people with very large catalogs and low memory settings
|
||||
; this is off by default as it does significantly increase the memory
|
||||
; requirments on larger catalogs. If you have the memory this can create
|
||||
; a 2-3x speed improvement.
|
||||
; DEFAULT: false
|
||||
memory_cache = "true"
|
||||
|
||||
; Memory Limit
|
||||
; This defines the "Min" memory limit for PHP if your php.ini
|
||||
; has a lower value set Ampache will set it up to this. If you
|
||||
; set it below 16MB getid3() will not work!
|
||||
; DEFAULT: 32
|
||||
;memory_limit = 32
|
||||
|
||||
; Album Art Preferred Filename
|
||||
; Specify a filename to look for if you always give the same filename
|
||||
; i.e. "folder.jpg" Ampache currently only supports jpg/gif and png
|
||||
; Especially useful if you have a front and a back image in a folder
|
||||
; comment out if ampache should search for any jpg,gif or png
|
||||
; DEFAULT: folder.jpg
|
||||
;album_art_preferred_filename = "folder.jpg"
|
||||
|
||||
; Album Art Store on Disk
|
||||
; This defines if arts should be stored on disk instead of database.
|
||||
; DEFAULT: false
|
||||
;album_art_store_disk = "false"
|
||||
|
||||
; Local Metadata Directory
|
||||
; This define a local metadata directory with write access where to store
|
||||
; heavy data if enabled (album arts, ...)
|
||||
; DEFAULT: none
|
||||
;local_metadata_dir = "/metadata"
|
||||
|
||||
; Maximal upload size
|
||||
; Specify the maximal allowed upload size for images, in bytes.
|
||||
; DEFAULT: 1048576
|
||||
;max_upload_size = 1048576
|
||||
|
||||
; Album Art Minimum Width
|
||||
; Specify the minimum width for arts (in pixel).
|
||||
; DEFAULT: none
|
||||
;album_art_min_width = 100
|
||||
|
||||
; Album Art Maximum Width
|
||||
; Specify the maximum width for arts (in pixel).
|
||||
; DEFAULT: none
|
||||
;album_art_max_width = 1024
|
||||
|
||||
; Album Art Minimum Height
|
||||
; Specify the minimum height for arts (in pixel).
|
||||
; DEFAULT: none
|
||||
;album_art_min_height = 100
|
||||
|
||||
; Album Art Maximum Height
|
||||
; Specify the maximum height for arts (in pixel).
|
||||
; DEFAULT: none
|
||||
;album_art_max_height = 1024
|
||||
|
||||
; Resize Images * Requires PHP-GD *
|
||||
; Set this to true if you want Ampache to resize the Album
|
||||
; art on the fly, this increases load time and CPU usage
|
||||
; and also requires the PHP-GD library. This is very useful
|
||||
; If you have high-quality album art and a small upload cap
|
||||
; DEFAULT: false
|
||||
;resize_images = "false"
|
||||
|
||||
; Statistical Graphs * Requires PHP-GD *
|
||||
; Set this to true if you want Ampache to generate statistical
|
||||
; graphs on usages / users.
|
||||
; DEFAULT: false
|
||||
;statistical_graphs = "false"
|
||||
|
||||
; Art Gather Order
|
||||
; Simply arrange the following in the order you would like
|
||||
; ampache to search. If you want to disable one of the search
|
||||
; methods simply leave it out. DB should be left as the first
|
||||
; method unless you want it to overwrite what's already in the
|
||||
; database
|
||||
; POSSIBLE VALUES (builtins): db tags folder lastfm musicbrainz google
|
||||
; POSSIBLE VALUES (plugins): Amazon,TheAudioDb,Tmdb,Omdb,Flickr
|
||||
; DEFAULT: db,tags,folder,musicbrainz,lastfm,google
|
||||
art_order = "db,tags,folder,musicbrainz,lastfm,google"
|
||||
|
||||
; Recommendations
|
||||
; Set this to true to enable display of similar artists or albums
|
||||
; while browsing. Requires Last.FM.
|
||||
; DEFAULT: false
|
||||
;show_similar = "false"
|
||||
|
||||
; Concerts
|
||||
; Set this to true to enable display of artist concerts
|
||||
; Requires Last.FM.
|
||||
; DEFAULT: false
|
||||
;show_concerts = "false"
|
||||
|
||||
; Last.FM API Key
|
||||
; Set this to your Last.FM api key to actually use Last.FM for
|
||||
; recommendations and metadata.
|
||||
lastfm_api_key = "d5df942424c71b754e54ce1832505ae2"
|
||||
|
||||
; Wanted
|
||||
; Set this to true to enable display missing albums and the
|
||||
; possibility for users to mark it as wanted.
|
||||
; DEFAULT: false
|
||||
wanted = "true"
|
||||
|
||||
; Wanted types
|
||||
; Set the allowed types of wanted releases (album,compilation,single,ep,live,remix,promotion,official)
|
||||
; DEFAULT: album,official
|
||||
wanted_types = "album,official"
|
||||
|
||||
; Wanted Auto Accept
|
||||
; Mark wanted requests as accepted by default (no content manager agreement required)
|
||||
; DEFAULT: false
|
||||
;wanted_auto_accept = "false"
|
||||
|
||||
; EchoNest API key
|
||||
; EchoNest provides several music services. Currently used for missing song 30 seconds preview.
|
||||
;echonest_api_key = ""
|
||||
|
||||
; Labels
|
||||
; Use labels to browse artists per label membership.
|
||||
; DEFAULT: false
|
||||
;label = "false"
|
||||
|
||||
; Broadcasts
|
||||
; Allow users to broadcast music.
|
||||
; This feature requires advanced server configuration, please take a look on the wiki for more information.
|
||||
; DEFAULT: false
|
||||
;broadcast = "false"
|
||||
|
||||
; Channels
|
||||
; Set this to true to enable channels and the
|
||||
; possibility for users to create channels from playlists
|
||||
; DEFAULT: true
|
||||
channel = "true"
|
||||
|
||||
; Live Streams
|
||||
; Set this to true to enable live streams (radio) and the
|
||||
; possibility for users to add new live streams.
|
||||
; DEFAULT: true
|
||||
live_stream = "true"
|
||||
|
||||
; Web Socket address
|
||||
; Declare the web socket server address
|
||||
; DEFAULT: determined automatically
|
||||
;websocket_address = "ws://localhost:8100"
|
||||
|
||||
; Debug
|
||||
; If this is enabled Ampache will write debugging information to the log file
|
||||
; DEFAULT: false
|
||||
debug = "true"
|
||||
|
||||
; Debug Level
|
||||
; This should always be set in conjunction with the
|
||||
; debug option, it defines how prolific you want the
|
||||
; debugging in ampache to be. values are 1-5.
|
||||
; 1 == Errors only
|
||||
; 2 == Error + Failures (login attempts etc.)
|
||||
; 3 == ??
|
||||
; 4 == ?? (Profit!)
|
||||
; 5 == Information (cataloging progress etc.)
|
||||
; DEFAULT: 5
|
||||
debug_level = "5"
|
||||
|
||||
; Path to Log File
|
||||
; This defines where you want ampache to log events to
|
||||
; this will only happen if debug is turned on. Do not
|
||||
; include trailing slash. You will need to make sure that
|
||||
; the specified directory exists and your HTTP server has
|
||||
; write access.
|
||||
; DEFAULT: NULL
|
||||
log_path = "/var/www/ampache/log"
|
||||
|
||||
; Log filename pattern
|
||||
; This defines where the log file name pattern.
|
||||
; %name.%Y%m%d.log will create a different log file every day.
|
||||
; DEFAULT: %name.%Y%m%d.log
|
||||
log_filename = "%name.%Y%m%d.log"
|
||||
|
||||
; Charset of generated HTML pages
|
||||
; Default of UTF-8 should work for most people
|
||||
; DEFAULT: UTF-8
|
||||
site_charset = "UTF-8"
|
||||
|
||||
; Locale Charset
|
||||
; Local charset (mainly for file operations) if different
|
||||
; from site_charset.
|
||||
; This is disabled by default, enable only if needed
|
||||
; (for Windows please set lc_charset to ISO8859-1)
|
||||
; DEFAULT: ISO8859-1
|
||||
;lc_charset = "ISO8859-1"
|
||||
|
||||
; Refresh Limit
|
||||
; This defines the default refresh limit in seconds for
|
||||
; pages with dynamic content, such as now playing
|
||||
; DEFAULT: 60
|
||||
; Possible Values: Int > 5
|
||||
refresh_limit = "60"
|
||||
|
||||
; Footer Statistics
|
||||
; This defines whether statistics (Queries, Cache Hits, Load Time)
|
||||
; are shown in the page footer.
|
||||
; DEFAULT: true
|
||||
; Possible values: true, false
|
||||
show_footer_statistics = "true"
|
||||
|
||||
;#########################################################
|
||||
; Custom actions (optional) #
|
||||
;#########################################################
|
||||
|
||||
; Your custom play action title
|
||||
;custom_play_action_title_0 = ""
|
||||
; Your custom play action icon name (stored as /images/icon_[your_image].png)
|
||||
;custom_play_action_icon_0 = ""
|
||||
; Your custom action script, where:
|
||||
; - %f: the media file path
|
||||
; - %c: the excepted codec target (mp3, ogg, ...)
|
||||
; - %a: the artist name
|
||||
; - %A: the album name
|
||||
; - %t: the song title
|
||||
;custom_play_action_run_0 = ""
|
||||
|
||||
; Example for Karaoke playing
|
||||
;custom_play_action_title_0 = "Karaoke"
|
||||
;custom_play_action_icon_0 = "microphone"
|
||||
;custom_play_action_run_0 = "sox \"%f\" -p oops | ffmpeg -i pipe:0 -f %c pipe:1"
|
||||
|
||||
;#########################################################
|
||||
; LDAP login info (optional) #
|
||||
;#########################################################
|
||||
|
||||
; LDAP filter string to use (required)
|
||||
; For OpenLDAP use "uid"
|
||||
; For Microsoft Active Directory (MAD) use "sAMAccountName"
|
||||
; DEFAULT: null
|
||||
;ldap_filter = "(sAMAccountName=%v)"
|
||||
|
||||
; LDAP objectclass (required)
|
||||
; OpanLDAP objectclass = "*"
|
||||
; MAD objectclass = "organizationalPerson"
|
||||
; DEFAULT null
|
||||
ldap_objectclass = "posixAccount"
|
||||
|
||||
; Initial credentials to bind with for searching (optional)
|
||||
; DEFAULT: null
|
||||
;ldap_username = ""
|
||||
;ldap_password = ""
|
||||
|
||||
; Require that the user is in a specific group (optional)
|
||||
; DEFAULT: null
|
||||
;ldap_require_group = "cn=yourgroup,ou=yourorg,dc=yoursubdomain,dc=yourdomain,dc=yourtld"
|
||||
|
||||
; This is the search dn used to find users (required)
|
||||
; DEFAULT: null
|
||||
ldap_search_dn = "dc=yunohost,dc=org"
|
||||
|
||||
; This is the address of your ldap server (required)
|
||||
; DEFAULT: null
|
||||
ldap_url = "localhost"
|
||||
|
||||
; Attributes where additional user information is stored (optional)
|
||||
; OpenLDAP ldap_name_field = "cn"
|
||||
; MAD ldap_name_field = "displayname"
|
||||
; DEFAULT: null
|
||||
;ldap_email_field = "mail"
|
||||
ldap_name_field = "cn"
|
||||
|
||||
;#########################################################
|
||||
; OpenID login info (optional) #
|
||||
;#########################################################
|
||||
|
||||
; Requires specific OpenID Provider Authentication Policy
|
||||
; DEFAULT: null
|
||||
; VALUES: PAPE_AUTH_MULTI_FACTOR_PHYSICAL,PAPE_AUTH_MULTI_FACTOR,PAPE_AUTH_PHISHING_RESISTANT
|
||||
;openid_required_pape = ""
|
||||
|
||||
;#########################################################
|
||||
; Public Registration settings, defaults to disabled #
|
||||
;#########################################################
|
||||
|
||||
; This setting will silently create an ampache account
|
||||
; for anyone who can login using ldap (or any other login
|
||||
; extension). The default is to create new users as guests
|
||||
; see auto_user config option if you would like to change this
|
||||
; DEFAULT: false
|
||||
auto_create = "true"
|
||||
|
||||
; This setting turns on/off public registration. It is
|
||||
; recommended you leave this off, as it will allow anyone to
|
||||
; sign up for an account on your server.
|
||||
; REMEMBER: don't forget to set the mail from address further down in the config.
|
||||
; DEFAULT: false
|
||||
;allow_public_registration = "false"
|
||||
|
||||
; Require Captcha Text on Image confirmation
|
||||
; Turning this on requires the user to correctly
|
||||
; type in the letters in the image created by Captcha
|
||||
; Default is off because its very hard to detect if it failed
|
||||
; to draw, or they failed to enter it.
|
||||
; DEFAULT: false
|
||||
;captcha_public_reg = "false"
|
||||
|
||||
; This setting turns on/off admin notification of registration.
|
||||
; DEFAULT: false
|
||||
;admin_notify_reg = "false"
|
||||
|
||||
; This setting determines whether the user will be created as a disabled user.
|
||||
; If this is on, an administrator will need to manually enable the account
|
||||
; before it's usable.
|
||||
; DEFAULT: false
|
||||
;admin_enable_required = "false"
|
||||
|
||||
; This setting will allow all registrants/ldap/http users
|
||||
; to be auto-approved as a user. By default, they will be
|
||||
; added as a guest and must be promoted by the admin.
|
||||
; POSSIBLE VALUES: guest, user, admin
|
||||
; DEFAULT: guest
|
||||
auto_user = "user"
|
||||
|
||||
; This will display the user agreement when registering
|
||||
; For agreement text, edit config/registration_agreement.php
|
||||
; User will need to accept the agreement before they can register
|
||||
; DEFAULT: false
|
||||
;user_agreement = "false"
|
||||
|
||||
; This disable email confirmation when registering.
|
||||
; DEFAULT: false
|
||||
;user_no_email_confirm = "false"
|
||||
|
||||
; This will display the cookie disclaimer (EU Cookie Law)
|
||||
; DEFAULT: false
|
||||
;cookie_disclaimer = "false"
|
||||
|
||||
; The fields that will be shown on Registration page
|
||||
; If a user wants to register.
|
||||
; Username and email fields are forced.
|
||||
; POSSIBLE VALUES: fullname,website,state,city
|
||||
; DEFAULT: "fullname,website"
|
||||
registration_display_fields = "fullname,website"
|
||||
|
||||
; The fields that will be mandatory
|
||||
; This controls which fields are mandatory for registration.
|
||||
; Username and email fields are forced mandatory.
|
||||
; POSSIBLE VALUES: fullname,website,state,city
|
||||
; DEFAULT: fullname
|
||||
registration_mandatory_fields = "fullname"
|
||||
|
||||
;########################################################
|
||||
; These options control the dynamic downsampling based #
|
||||
; on current usage #
|
||||
; *Note* Transcoding must be enabled and working #
|
||||
;########################################################
|
||||
|
||||
; Attempt to optimize bandwidth by dynamically lowering the bit rate of new
|
||||
; streams. Since the bit rate is only adjusted at the beginning of a song, the
|
||||
; actual cumulative bitrate for concurrent streams can be up to around
|
||||
; double the configured value. It also only applies to streams that are
|
||||
; transcoded.
|
||||
; DEFAULT: none
|
||||
max_bit_rate = "576"
|
||||
|
||||
; New dynamically downsampled streams will be denied if they are forced below
|
||||
; this value.
|
||||
; DEFAULT: 8
|
||||
min_bit_rate = "48"
|
||||
|
||||
;######################################################
|
||||
; These are commands used to transcode non-streaming
|
||||
; formats to the target file type for streaming.
|
||||
; This can be useful in re-encoding file types that don't stream
|
||||
; very well, or if your player doesn't support some file types.
|
||||
;
|
||||
; 'Downsampling' will also use these commands.
|
||||
;
|
||||
; To state the bleeding obvious, any programs referenced in the transcode
|
||||
; commands must be installed, in the web server's search path (or referenced
|
||||
; by their full path), and executable by the web server.
|
||||
|
||||
; Input type selection
|
||||
; TYPE is the extension. 'allowed' certifies that transcoding works properly for
|
||||
; this input format. 'required' further forbids the direct streaming of a format
|
||||
; (e.g. if you store everything in FLAC, but don't want to ever stream that.)
|
||||
; transcode_TYPE = {allowed|required|false}
|
||||
; DEFAULT: false
|
||||
;;; Audio
|
||||
;transcode_m4a = allowed
|
||||
transcode_flac = "required"
|
||||
;transcode_mpc = required
|
||||
;transcode_ogg = required
|
||||
;transcode_oga = required
|
||||
;transcode_wav = required
|
||||
;transcode_wma = required
|
||||
;transcode_aif = required
|
||||
;transcode_aiff = required
|
||||
;transcode_ape = required
|
||||
;transcode_shn = required
|
||||
transcode_mp3 = "allowed"
|
||||
;;; Video
|
||||
;transcode_avi = allowed
|
||||
;transcode_mkv = allowed
|
||||
;transcode_mpg = allowed
|
||||
;transcode_mpeg = allowed
|
||||
;transcode_m4v = allowed
|
||||
;transcode_mp4 = allowed
|
||||
;transcode_mov = allowed
|
||||
;transcode_wmv = allowed
|
||||
;transcode_ogv = allowed
|
||||
;transcode_divx = allowed
|
||||
;transcode_m2ts = allowed
|
||||
;transcode_webm = allowed
|
||||
|
||||
; Default audio output format
|
||||
; DEFAULT: none
|
||||
encode_target = "mp3"
|
||||
|
||||
; Default video output format
|
||||
; DEFAULT: none
|
||||
;encode_video_target = webm
|
||||
|
||||
; Override the default output format on a per-type basis
|
||||
; encode_target_TYPE = TYPE
|
||||
; DEFAULT: none
|
||||
;encode_target_flac = ogg
|
||||
|
||||
; Override the default TYPE transcoding behavior on a per-player basis
|
||||
; transcode_player_PLAYER_TYPE = TYPE
|
||||
; Valid PLAYER is: webplayer, api
|
||||
; DEFAULT: none
|
||||
;transcode_player_webplayer_m4a = required
|
||||
;transcode_player_webplayer_flac = required
|
||||
;transcode_player_webplayer_mpc = required
|
||||
|
||||
; Override the default output format on a per-player basis
|
||||
; encode_player_PLAYER_target = TYPE
|
||||
; Valid PLAYER is: webplayer, api
|
||||
; DEFAULT: none
|
||||
;encode_player_webplayer_target = mp3
|
||||
;encode_player_api_target = mp3
|
||||
|
||||
; Allow clients to override transcode settings (output type, bitrate, codec ...)
|
||||
; DEFAULT: true
|
||||
transcode_player_customize = "1"
|
||||
|
||||
; Command configuration. Substitutions will be made as follows:
|
||||
; %FILE% => filename
|
||||
; %SAMPLE% => target sample rate
|
||||
; You can do fancy things like VBR, but consider whether the consequences are
|
||||
; acceptable in your environment.
|
||||
|
||||
; Master transcode command
|
||||
; transcode_cmd should be a single command that supports multiple file types,
|
||||
; such as ffmpeg or avconv. It's still possible to make a configuration that's
|
||||
; equivalent to the old default, but if you find that necessary you should be
|
||||
; clever enough to figure out how on your own.
|
||||
; DEFAULT: none
|
||||
transcode_cmd = "ffmpeg -i %FILE%"
|
||||
;transcode_cmd = "avconv"
|
||||
;transcode_cmd = "/usr/bin/neatokeen"
|
||||
|
||||
; Transcode input file argument
|
||||
transcode_input = "-i %FILE%"
|
||||
|
||||
; Specific transcode commands
|
||||
; It shouldn't be necessary in most cases, but you can override the transcode
|
||||
; command for specific source formats. It still needs to accept the
|
||||
; encoding arguments, so the easiest approach is to use your normal command as
|
||||
; a clearing-house.
|
||||
; transcode_cmd_TYPE = TRANSCODE_CMD
|
||||
;transcode_cmd_mid = "timidity -Or -o – %FILE% | ffmpeg -f s16le -i pipe:0"
|
||||
|
||||
; Encoding arguments
|
||||
; For each output format, you should provide the necessary arguments for
|
||||
; your transcode_cmd.
|
||||
; encode_args_TYPE = TRANSCODE_CMD_ARGS
|
||||
encode_args_mp3 = "-vn -b:a %SAMPLE%K -acodec libmp3lame -f mp3 pipe:1"
|
||||
encode_args_ogg = "-vn -b:a max\(%SAMPLE%K\,49K\) -acodec libvorbis -vcodec libtheora -f ogg pipe:1"
|
||||
encode_args_m4a = "-vn -b:a %SAMPLE%K -c:a libfdk_aac -f adts pipe:1"
|
||||
encode_args_wav = "-vn -b:a %SAMPLE%K -c:a pcm_s16le -f wav pipe:1"
|
||||
encode_args_flv = "-b:a %SAMPLE%K -ar 44100 -ac 2 -v 0 -f flv -c:v libx264 -preset superfast -threads 0 pipe:1"
|
||||
encode_args_webm = "-q %QUALITY% -f webm -c:v libvpx -maxrate %MAXBITRATE%k -preset superfast -threads 0 pipe:1"
|
||||
encode_args_ts = "-q %QUALITY% -s %RESOLUTION% -f mpegts -c:v libx264 -c:a libmp3lame -maxrate %MAXBITRATE%k -preset superfast -threads 0 pipe:1"
|
||||
|
||||
; Encoding arguments to retrieve an image from a single frame
|
||||
encode_get_image = "-ss %TIME% -f image2 -vframes 1 pipe:1"
|
||||
|
||||
; Encoding argument to encrust subtitle
|
||||
encode_srt = "-vf \"subtitles='%SRTFILE%'\""
|
||||
|
||||
; Encode segment frame argument
|
||||
encode_ss_frame = "-ss %TIME%"
|
||||
|
||||
; Encode segment duration argument
|
||||
encode_ss_duration = "-t %DURATION%"
|
||||
|
||||
|
||||
;######################################################
|
||||
; these options allow you to configure your rss-feed
|
||||
; layout. rss exists of two parts, main and song main is the information about the feed
|
||||
; song is the information in the feed. can be multiple items.
|
||||
; use_rss = false (values true | false)
|
||||
;DEFAULT: use_rss = false
|
||||
;use_rss = "false"
|
||||
;#####################################################
|
||||
|
||||
;#############################
|
||||
; Proxy Settings (optional) #
|
||||
;#############################
|
||||
; If Ampache is behind an http proxy, specifiy the hostname or IP address
|
||||
; port, proxyusername, and proxypassword here.
|
||||
;DEFAULT: not in use
|
||||
;proxy_host = "192.168.0.1"
|
||||
;proxy_port = "8080"
|
||||
;proxy_user = ""
|
||||
;proxy_pass = ""
|
||||
|
||||
; If Ampache is behind an https reverse proxy, force use HTTPS protocol.
|
||||
;Default: false
|
||||
force_ssl = "1"
|
||||
|
||||
;#############################
|
||||
; Mail Settings #
|
||||
;#############################
|
||||
|
||||
;Method used to send mail
|
||||
;POSSIBLE VALUES: smtp sendmail php
|
||||
;DEFAULT: php
|
||||
;mail_type = "php"
|
||||
|
||||
;Mail domain.
|
||||
;DEFAULT: example.com
|
||||
;mail_domain = "example.com"
|
||||
|
||||
;This will be combined with mail_domain and used as the source address for
|
||||
;emails generated by Ampache. For example, setting this to 'me' will set the
|
||||
;sender to 'me@example.com'.
|
||||
;DEFAULT: info
|
||||
;mail_user = "info"
|
||||
|
||||
;A name to go with the email address.
|
||||
;DEFAULT: Ampache
|
||||
;mail_name = "Ampache"
|
||||
|
||||
;How strictly email addresses should be checked.
|
||||
;easy does a regex match, strict actually performs some SMTP transactions
|
||||
;to see if we can send to this address.
|
||||
;POSSIBLE VALUES: strict easy none
|
||||
; DEFAULT: strict
|
||||
;mail_check = "strict"
|
||||
|
||||
|
||||
;############################
|
||||
; sendmail Settings #
|
||||
;############################
|
||||
|
||||
;DEFAULT: /usr/sbin/sendmail
|
||||
;sendmail_path = "/usr/sbin/sendmail"
|
||||
|
||||
;#############################
|
||||
; SMTP Settings #
|
||||
;#############################
|
||||
|
||||
;Mail server (hostname or IP address)
|
||||
;DEFAULT: localhost
|
||||
;mail_host = "localhost"
|
||||
|
||||
; SMTP port
|
||||
;DEFAULT: 25
|
||||
;mail_port = 25
|
||||
|
||||
;Secure SMTP
|
||||
;POSSIBLE VALUES: ssl tls
|
||||
;DEFAULT: none
|
||||
;mail_secure_smtp = tls
|
||||
|
||||
;Enable SMTP authentication
|
||||
;DEFAULT: false
|
||||
;mail_auth = "true"
|
||||
|
||||
;SMTP Username
|
||||
;your mail auth username.
|
||||
;mail_auth_user = ""
|
||||
|
||||
; SMTP Password
|
||||
; your mail auth password.
|
||||
;mail_auth_pass = ""
|
||||
|
||||
;#############################
|
||||
; Multibyte Settings #
|
||||
;#############################
|
||||
; See http://php.net/manual/mbstring.supported-encodings.php
|
||||
; If you want ID3v1 encoding detection to work, you should uncomment this line
|
||||
; so that the ordering is sane.
|
||||
; DEFAULT: auto
|
||||
;mb_detect_order = "ASCII,UTF-8,EUC-JP,ISO-2022-JP,SJIS,JIS"
|
||||
|
||||
slideshow_time = 0
|
||||
|
|
@ -14,6 +14,7 @@ location PATHTOCHANGE {
|
|||
include fastcgi_params;
|
||||
fastcgi_param REMOTE_USER $remote_user;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||
}
|
||||
|
||||
rewrite ^PATHTOCHANGE/play/ssid/(\w+)/type/(\w+)/oid/([0-9]+)/uid/([0-9]+)/name/(.*)$ PATHTOCHANGE/play/index.php?ssid=$1&type=$2&oid=$3&uid=$4&name=$5 last;
|
||||
|
|
|
@ -67,6 +67,7 @@ sleep 5
|
|||
sudo yunohost app setting ampache skipped_uris -d
|
||||
sudo yunohost app setting ampache skipped_uris -v "/rest"
|
||||
sudo yunohost app ssowatconf
|
||||
sudo sed -i '/yunoampache/d' /etc/hosts
|
||||
sudo sed '/yunoampache/d' /etc/hosts > /tmp/hosts.tmp
|
||||
sudo cp /tmp/hosts.tmp /etc/hosts ; sudo rm -f /tmp/hosts.tmp
|
||||
mysql -u $db_user -p$db_pwd $db_user < /tmp/admin.sql
|
||||
sudo rm /tmp/admin.sql
|
||||
|
|
63
sources/.gitattributes
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
12
sources/.gitignore
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
config/ampache.cfg.php
|
||||
config/ampache-doped.cfg.php
|
||||
rest/.htaccess
|
||||
play/.htaccess
|
||||
*.phpproj
|
||||
*.sln
|
||||
*.v11.suo
|
||||
*.suo
|
||||
logs
|
||||
/nbproject/private/
|
||||
.pc
|
||||
/tmp
|
22
sources/.maintenance.example
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
/**
|
||||
* To put your Ampache website in maintenance, just rename this file to .maintenance
|
||||
* This example redirect your visitors to a default maintenance information page hosted in ampache.org
|
||||
*/
|
||||
|
||||
header("Access-Control-Allow-Origin: *");
|
||||
header("Access-Control-Allow-Methods: GET, POST");
|
||||
|
||||
$domain = $_SERVER['HTTP_HOST'];
|
||||
if (empty($domain)) {
|
||||
$domain = $_SERVER['SERVER_NAME'];
|
||||
}
|
||||
$scheme = "http";
|
||||
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
|
||||
$scheme = "https";
|
||||
}
|
||||
$fromurl = rawurlencode($scheme . "://" . $domain . $_SERVER[REQUEST_URI]);
|
||||
|
||||
header("Location: http://ampache.org/maintenance/?from=" . $fromurl);
|
||||
exit;
|
||||
?>
|
16
sources/.php_cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
use Symfony\CS\FixerInterface;
|
||||
|
||||
$finder = Symfony\CS\Finder\DefaultFinder::create()
|
||||
->exclude('modules')
|
||||
->exclude('nbproject')
|
||||
->in(__DIR__)
|
||||
->in(__DIR__ . '/modules/localplay')
|
||||
->in(__DIR__ . '/modules/catalog')
|
||||
->in(__DIR__ . '/modules/ampacheapi')
|
||||
;
|
||||
|
||||
return Symfony\CS\Config\Config::create()
|
||||
->finder($finder)
|
||||
;
|
59
sources/.scrutinizer.yml
Normal file
|
@ -0,0 +1,59 @@
|
|||
filter:
|
||||
excluded_paths:
|
||||
- 'modules/*'
|
||||
paths: { }
|
||||
|
||||
tools:
|
||||
php_mess_detector:
|
||||
enabled: true
|
||||
filter:
|
||||
excluded_paths:
|
||||
- 'modules/*'
|
||||
- 'themes/*'
|
||||
paths: { }
|
||||
php_code_sniffer:
|
||||
enabled: false
|
||||
php_pdepend:
|
||||
enabled: true
|
||||
configuration_file: null
|
||||
suffixes:
|
||||
- php
|
||||
excluded_dirs: { }
|
||||
filter:
|
||||
excluded_paths:
|
||||
- 'modules/*'
|
||||
paths: { }
|
||||
php_analyzer:
|
||||
enabled: true
|
||||
extensions:
|
||||
- php
|
||||
dependency_paths:
|
||||
- 'modules/*'
|
||||
filter:
|
||||
excluded_paths:
|
||||
- 'modules/*'
|
||||
- 'themes/*'
|
||||
paths: { }
|
||||
path_configs: { }
|
||||
php_changetracking:
|
||||
enabled: true
|
||||
bug_patterns:
|
||||
- '\bfix(?:es|ed)?\b'
|
||||
feature_patterns:
|
||||
- '\badd(?:s|ed)?\b'
|
||||
- '\bimplement(?:s|ed)?\b'
|
||||
filter:
|
||||
excluded_paths:
|
||||
- 'modules/*'
|
||||
paths: { }
|
||||
php_loc:
|
||||
enabled: true
|
||||
excluded_dirs:
|
||||
- 'modules/*'
|
||||
php_cpd:
|
||||
enabled: true
|
||||
excluded_dirs: { }
|
||||
filter:
|
||||
excluded_paths:
|
||||
- 'modules/*'
|
||||
paths: { }
|
6
sources/.tgitconfig
Normal file
|
@ -0,0 +1,6 @@
|
|||
[bugtraq]
|
||||
url = "https://github.com/ampache/ampache/issues/#BUGID#"
|
||||
label = GitHub Issue Number
|
||||
warnifnoissue = false
|
||||
number = true
|
||||
logregex = "#\\d+\n\\d+"
|
17
sources/.travis.yml
Normal file
|
@ -0,0 +1,17 @@
|
|||
language: php
|
||||
|
||||
php:
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
|
||||
before_install:
|
||||
- wget http://cs.sensiolabs.org/get/php-cs-fixer.phar
|
||||
|
||||
before_script:
|
||||
- chmod +x scripts/tests/syntax.sh
|
||||
- chmod +x scripts/tests/codestyle.sh
|
||||
|
||||
script:
|
||||
- scripts/tests/syntax.sh
|
||||
- scripts/tests/codestyle.sh
|
8
sources/.tx/config
Normal file
|
@ -0,0 +1,8 @@
|
|||
[main]
|
||||
host = https://www.transifex.com
|
||||
|
||||
[project_slug.resource_slug]
|
||||
file_filter = locale/<lang>_<lang>/LC_MESSAGES/messages.po
|
||||
source_file = locale/base/messages.pot
|
||||
source_lang = en_US
|
||||
type = PO
|
1
sources/CNAME
Normal file
|
@ -0,0 +1 @@
|
|||
ampache.org
|
6
sources/CONTRIBUTING.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
## Contribution
|
||||
Please read [Development section](https://github.com/ampache/ampache/wiki#development).
|
||||
|
||||
## Bug report
|
||||
Be sure the bug is not already fixed in `develop` branch or already reported in current open issues.
|
||||
Please add [some logs](https://github.com/ampache/ampache/wiki/Troubleshooting#enable-logging) with your new issue.
|
|
@ -22,11 +22,13 @@ Recommended Version
|
|||
|
||||
Currently, the recommended version is [git HEAD](https://github.com/ampache/ampache/archive/master.tar.gz).
|
||||
[](https://travis-ci.org/ampache/ampache)
|
||||
[](https://scrutinizer-ci.com/g/ampache/ampache/?branch=master)
|
||||
|
||||
Latest changes but unstable is [develop branch](https://github.com/ampache/ampache/archive/develop.tar.gz).
|
||||
[](https://travis-ci.org/ampache/ampache)
|
||||
[](https://scrutinizer-ci.com/g/ampache/ampache/?branch=develop)
|
||||
[](https://www.codacy.com/app/afterster_2222/ampache)
|
||||
[](https://codeclimate.com/github/ampache/ampache)
|
||||
[](https://insight.sensiolabs.com/projects/ee067d0e-3432-4062-a969-01b4ee037f48)
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
@ -38,7 +40,7 @@ receives the most testing:
|
|||
* nginx
|
||||
* IIS
|
||||
|
||||
* PHP 5.3 or greater.
|
||||
* PHP 5.4 or greater.
|
||||
|
||||
* PHP modules:
|
||||
* PDO
|
||||
|
@ -46,6 +48,8 @@ receives the most testing:
|
|||
* hash
|
||||
* session
|
||||
* json
|
||||
* simplexml (This is not strictly necessary, but may result in a better experience.)
|
||||
* curl (This is not strictly necessary, but may result in a better experience.)
|
||||
|
||||
* MySQL 5.x
|
||||
|
||||
|
@ -59,8 +63,8 @@ Upgrading
|
|||
|
||||
If you are upgrading from an older version of Ampache we recommend
|
||||
moving the old directory out of the way, extracting the new copy in
|
||||
its place and then copying the old config file into config/. All
|
||||
database updates will be handled by Ampache.
|
||||
its place and then copying the old config/ampache.cfg.php, /rest/.htaccess,
|
||||
and /play/.htaccess files if any. All database updates will be handled by Ampache.
|
||||
|
||||
License
|
||||
-------
|
||||
|
@ -99,6 +103,15 @@ Ampache includes some external modules that carry their own licensing.
|
|||
* [MediaTable] (https://github.com/edenspiekermann/MediaTable): MIT
|
||||
* [Responsive Elements] (https://github.com/kumailht/responsive-elements): MIT
|
||||
* [Bootstrap] (http://getbootstrap.com): MIT
|
||||
* [jQuery Knob] (https://github.com/aterrien/jQuery-Knob): MIT
|
||||
* [jQuery File Upload] (https://github.com/blueimp/jQuery-File-Upload): MIT
|
||||
* [jsTree] (http://www.jstree.com): MIT
|
||||
* [php-tmdb-api] (https://github.com/wtfzdotnet/php-tmdb-api) : MIT
|
||||
* [TvDb] (https://github.com/Moinax/TvDb) : MIT
|
||||
* [jQuery DateTimePicker] (https://github.com/xdan/datetimepicker) : MIT
|
||||
* [pChart] (http://www.pchart.net) : GPL v3
|
||||
* [ZipStream-PHP] (https://github.com/maennchen/ZipStream-PHP) : [ZipStream-PHP license] (modules/zipstream/COPYING)
|
||||
* [SabreDAV] (https://github.com/fruux/sabre-dav) : New BSD
|
||||
|
||||
|
||||
Translations
|
||||
|
@ -109,19 +122,24 @@ following languages. If you are interested in updating an existing
|
|||
translation or adding a new one please see /locale/base/TRANSLATIONS
|
||||
for more instructions.
|
||||
|
||||
* English (en_US)
|
||||
* German (de_DE)
|
||||
* Spanish (es_ES)
|
||||
* Dutch (nl_NL)
|
||||
* Norwegian (nb_NO)
|
||||
* UK English (en_GB)
|
||||
* Italian (it_IT)
|
||||
* French (fr_FR)
|
||||
* Swedish (sv_SE)
|
||||
* Japanese (ja_JP)
|
||||
* Catalan (ca_ES)
|
||||
* Russian (ru_RU)
|
||||
* Czech (cs_CZ)
|
||||
* English (en_US)
|
||||
* Arabic (ar_SA)
|
||||
* Catalan (ca_ES)
|
||||
* Catalan (ca_ES)
|
||||
* Czech (cs_CZ)
|
||||
* Dutch (nl_NL)
|
||||
* French (fr_FR)
|
||||
* German (de_DE)
|
||||
* Greek (el_GR)
|
||||
* Italian (it_IT)
|
||||
* Japanese (ja_JP)
|
||||
* Norwegian (nb_NO)
|
||||
* Persian (fa_IR)
|
||||
* Polish (pl_PL)
|
||||
* Russian (ru_RU)
|
||||
* Spanish (es_ES)
|
||||
* Swedish (sv_SE)
|
||||
* UK English (en_GB)
|
||||
|
||||
Credits
|
||||
-------
|
||||
|
@ -137,6 +155,7 @@ more features, encounter bugs, etc.
|
|||
|
||||
* [Public Repository](http://github.com/ampache)
|
||||
* IRC: chat.freenode.net #ampache
|
||||
* [Forum](https://groups.google.com/forum/#!forum/ampache)
|
||||
* [Issue Tracker](https://github.com/ampache/ampache/issues)
|
||||
* [Documentation](https://github.com/ampache/ampache/wiki)
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -30,74 +30,57 @@ if (!Access::check('interface','100')) {
|
|||
|
||||
UI::show_header();
|
||||
|
||||
$catalogs = $_REQUEST['catalogs'];
|
||||
// If only one catalog, check it is ready.
|
||||
if (is_array($catalogs) && count($catalogs) == 1 && $_REQUEST['action'] !== 'delete_catalog' && $_REQUEST['action'] !== 'show_delete_catalog') {
|
||||
// If not ready, display the data to make it ready / stop the action.
|
||||
$catalog = Catalog::create_from_id($catalogs[0]);
|
||||
if (!$catalog->isReady()) {
|
||||
if (!isset($_REQUEST['perform_ready'])) {
|
||||
$catalog->show_ready_process();
|
||||
UI::show_footer();
|
||||
exit;
|
||||
} else {
|
||||
$catalog->perform_ready();
|
||||
}
|
||||
}
|
||||
}
|
||||
$sse_catalogs = urlencode(serialize($catalogs));
|
||||
|
||||
/* Big switch statement to handle various actions */
|
||||
switch ($_REQUEST['action']) {
|
||||
case 'add_to_all_catalogs':
|
||||
$_REQUEST['catalogs'] = Catalog::get_catalogs();
|
||||
$sse_url = AmpConfig::get('web_path') . "/server/sse.server.php?worker=catalog&action=add_to_all_catalogs";
|
||||
sse_worker($sse_url);
|
||||
show_confirmation(T_('Catalog Update started...'), '', AmpConfig::get('web_path') . '/admin/catalog.php', 0, 'confirmation', false);
|
||||
break;
|
||||
case 'add_to_catalog':
|
||||
toggle_visible('ajax-loading');
|
||||
ob_end_flush();
|
||||
if (AmpConfig::get('demo_mode')) { break; }
|
||||
if ($_REQUEST['catalogs']) {
|
||||
foreach ($_REQUEST['catalogs'] as $catalog_id) {
|
||||
$catalog = Catalog::create_from_id($catalog_id);
|
||||
$catalog->add_to_catalog($_POST);
|
||||
}
|
||||
}
|
||||
$url = AmpConfig::get('web_path') . '/admin/catalog.php';
|
||||
$title = T_('Catalog Updated');
|
||||
$body = '';
|
||||
show_confirmation($title, $body, $url);
|
||||
toggle_visible('ajax-loading');
|
||||
|
||||
$sse_url = AmpConfig::get('web_path') . "/server/sse.server.php?worker=catalog&action=add_to_catalog&catalogs=" . $sse_catalogs;
|
||||
sse_worker($sse_url);
|
||||
show_confirmation(T_('Catalog Update started...'), '', AmpConfig::get('web_path') . '/admin/catalog.php', 0, 'confirmation', false);
|
||||
break;
|
||||
case 'update_all_catalogs':
|
||||
$_REQUEST['catalogs'] = Catalog::get_catalogs();
|
||||
$sse_url = AmpConfig::get('web_path') . "/server/sse.server.php?worker=catalog&action=update_all_catalogs";
|
||||
sse_worker($sse_url);
|
||||
show_confirmation(T_('Catalog Update started...'), '', AmpConfig::get('web_path') . '/admin/catalog.php', 0, 'confirmation', false);
|
||||
break;
|
||||
case 'update_catalog':
|
||||
toggle_visible('ajax-loading');
|
||||
ob_end_flush();
|
||||
/* If they are in demo mode stop here */
|
||||
if (AmpConfig::get('demo_mode')) { break; }
|
||||
if (AmpConfig::get('demo_mode')) { break; }
|
||||
|
||||
if (isset($_REQUEST['catalogs'])) {
|
||||
foreach ($_REQUEST['catalogs'] as $catalog_id) {
|
||||
$catalog = Catalog::create_from_id($catalog_id);
|
||||
$catalog->verify_catalog();
|
||||
}
|
||||
}
|
||||
$url = AmpConfig::get('web_path') . '/admin/catalog.php';
|
||||
$title = T_('Catalog Updated');
|
||||
$body = '';
|
||||
show_confirmation($title,$body,$url);
|
||||
toggle_visible('ajax-loading');
|
||||
$sse_url = AmpConfig::get('web_path') . "/server/sse.server.php?worker=catalog&action=update_catalog&catalogs=" . $sse_catalogs;
|
||||
sse_worker($sse_url);
|
||||
show_confirmation(T_('Catalog Update started...'), '', AmpConfig::get('web_path') . '/admin/catalog.php', 0, 'confirmation', false);
|
||||
break;
|
||||
case 'full_service':
|
||||
toggle_visible('ajax-loading');
|
||||
ob_end_flush();
|
||||
/* Make sure they aren't in demo mode */
|
||||
if (AmpConfig::get('demo_mode')) { UI::access_denied(); break; }
|
||||
|
||||
if (!$_REQUEST['catalogs']) {
|
||||
$_REQUEST['catalogs'] = Catalog::get_catalogs();
|
||||
}
|
||||
|
||||
/* This runs the clean/verify/add in that order */
|
||||
foreach ($_REQUEST['catalogs'] as $catalog_id) {
|
||||
$catalog = Catalog::create_from_id($catalog_id);
|
||||
$catalog->clean_catalog();
|
||||
$catalog->count = 0;
|
||||
$catalog->verify_catalog();
|
||||
$catalog->count = 0;
|
||||
$catalog->add_to_catalog();
|
||||
}
|
||||
Dba::optimize_tables();
|
||||
$url = AmpConfig::get('web_path') . '/admin/catalog.php';
|
||||
$title = T_('Catalog Updated');
|
||||
$body = '';
|
||||
show_confirmation($title,$body,$url);
|
||||
toggle_visible('ajax-loading');
|
||||
$sse_url = AmpConfig::get('web_path') . "/server/sse.server.php?worker=catalog&action=full_service&catalogs=" . $sse_catalogs;
|
||||
sse_worker($sse_url);
|
||||
show_confirmation(T_('Catalog Update started...'), '', AmpConfig::get('web_path') . '/admin/catalog.php', 0, 'confirmation', false);
|
||||
break;
|
||||
case 'delete_catalog':
|
||||
/* Make sure they aren't in demo mode */
|
||||
if (AmpConfig::get('demo_mode')) { break; }
|
||||
|
||||
if (!Core::form_verify('delete_catalog')) {
|
||||
|
@ -105,15 +88,21 @@ switch ($_REQUEST['action']) {
|
|||
exit;
|
||||
}
|
||||
|
||||
$deleted = true;
|
||||
/* Delete the sucker, we don't need to check perms as thats done above */
|
||||
Catalog::delete($_GET['catalog_id']);
|
||||
foreach ($catalogs as $catalog_id) {
|
||||
$deleted = Catalog::delete($catalog_id);
|
||||
if (!$deleted) break;
|
||||
}
|
||||
$next_url = AmpConfig::get('web_path') . '/admin/catalog.php';
|
||||
show_confirmation(T_('Catalog Deleted'), T_('The Catalog and all associated records have been deleted'),$next_url);
|
||||
if ($deleted) {
|
||||
show_confirmation(T_('Catalog Deleted'), T_('The Catalog and all associated records have been deleted'), $next_url);
|
||||
} else {
|
||||
show_confirmation(T_('Error'), T_('Cannot delete the catalog'), $next_url);
|
||||
}
|
||||
break;
|
||||
case 'show_delete_catalog':
|
||||
$catalog_id = scrub_in($_GET['catalog_id']);
|
||||
|
||||
$next_url = AmpConfig::get('web_path') . '/admin/catalog.php?action=delete_catalog&catalog_id=' . scrub_out($catalog_id);
|
||||
$next_url = AmpConfig::get('web_path') . '/admin/catalog.php?action=delete_catalog&catalogs[]=' . implode(',', $catalogs);
|
||||
show_confirmation(T_('Catalog Delete'), T_('Confirm Deletion Request'),$next_url,1,'delete_catalog');
|
||||
break;
|
||||
case 'enable_disabled':
|
||||
|
@ -134,27 +123,14 @@ switch ($_REQUEST['action']) {
|
|||
show_confirmation($title,$body,$url);
|
||||
break;
|
||||
case 'clean_all_catalogs':
|
||||
$_REQUEST['catalogs'] = Catalog::get_catalogs();
|
||||
$sse_url = AmpConfig::get('web_path') . "/server/sse.server.php?worker=catalog&action=clean_all_catalogs";
|
||||
sse_worker($sse_url);
|
||||
show_confirmation(T_('Catalog Clean started...'), '', AmpConfig::get('web_path') . '/admin/catalog.php', 0, 'confirmation', false);
|
||||
break;
|
||||
case 'clean_catalog':
|
||||
toggle_visible('ajax-loading');
|
||||
ob_end_flush();
|
||||
/* If they are in demo mode stop them here */
|
||||
if (AmpConfig::get('demo_mode')) { break; }
|
||||
|
||||
// Make sure they checked something
|
||||
if (isset($_REQUEST['catalogs'])) {
|
||||
foreach ($_REQUEST['catalogs'] as $catalog_id) {
|
||||
$catalog = Catalog::create_from_id($catalog_id);
|
||||
$catalog->clean_catalog();
|
||||
} // end foreach catalogs
|
||||
Dba::optimize_tables();
|
||||
}
|
||||
|
||||
$url = AmpConfig::get('web_path') . '/admin/catalog.php';
|
||||
$title = T_('Catalog Cleaned');
|
||||
$body = '';
|
||||
show_confirmation($title,$body,$url);
|
||||
toggle_visible('ajax-loading');
|
||||
$sse_url = AmpConfig::get('web_path') . "/server/sse.server.php?worker=catalog&action=clean_catalog&catalogs=" . $sse_catalogs;
|
||||
sse_worker($sse_url);
|
||||
show_confirmation(T_('Catalog Clean started...'), '', AmpConfig::get('web_path') . '/admin/catalog.php', 0, 'confirmation', false);
|
||||
break;
|
||||
case 'update_catalog_settings':
|
||||
/* No Demo Here! */
|
||||
|
@ -171,23 +147,9 @@ switch ($_REQUEST['action']) {
|
|||
case 'update_from':
|
||||
if (AmpConfig::get('demo_mode')) { break; }
|
||||
|
||||
// First see if we need to do an add
|
||||
if ($_POST['add_path'] != '/' AND strlen($_POST['add_path'])) {
|
||||
if ($catalog_id = Catalog_local::get_from_path($_POST['add_path'])) {
|
||||
$catalog = Catalog::create_from_id($catalog_id);
|
||||
$catalog->add_to_catalog(array('subdirectory'=>$_POST['add_path']));
|
||||
}
|
||||
} // end if add
|
||||
|
||||
// Now check for an update
|
||||
if ($_POST['update_path'] != '/' AND strlen($_POST['update_path'])) {
|
||||
if ($catalog_id = Catalog_local::get_from_path($_POST['update_path'])) {
|
||||
$songs = Song::get_from_path($_POST['update_path']);
|
||||
foreach ($songs as $song_id) { Catalog::update_single_item('song',$song_id); }
|
||||
}
|
||||
} // end if update
|
||||
|
||||
echo T_("Done.");
|
||||
$sse_url = AmpConfig::get('web_path') . "/server/sse.server.php?worker=catalog&action=update_from&add_path=" . scrub_in($_POST['add_path']) . "&update_path=" . $_POST['update_path'];
|
||||
sse_worker($sse_url);
|
||||
show_confirmation(T_('Subdirectory update started...'), '', AmpConfig::get('web_path') . '/admin/catalog.php', 0, 'confirmation', false);
|
||||
break;
|
||||
case 'add_catalog':
|
||||
/* Wah Demo! */
|
||||
|
@ -218,19 +180,10 @@ switch ($_REQUEST['action']) {
|
|||
break;
|
||||
}
|
||||
|
||||
$catalog = Catalog::create_from_id($catalog_id);
|
||||
|
||||
// Run our initial add
|
||||
$catalog->add_to_catalog($_POST);
|
||||
|
||||
UI::show_box_top(T_('Catalog Created'), 'box box_catalog_created');
|
||||
echo "<h2>" . T_('Catalog Created') . "</h2>";
|
||||
Error::display('general');
|
||||
Error::display('catalog_add');
|
||||
UI::show_box_bottom();
|
||||
|
||||
show_confirmation('','', AmpConfig::get('web_path').'/admin/catalog.php');
|
||||
$sse_url = AmpConfig::get('web_path') . "/server/sse.server.php?worker=catalog&action=add_catalog&catalog_id=" . $catalog_id . "&options=" . urlencode(serialize($_POST));
|
||||
sse_worker($sse_url);
|
||||
|
||||
show_confirmation(T_('Catalog Creation started...'), '', AmpConfig::get('web_path') . '/admin/catalog.php', 0, 'confirmation', false);
|
||||
} else {
|
||||
require AmpConfig::get('prefix') . '/templates/show_add_catalog.inc.php';
|
||||
}
|
||||
|
@ -275,23 +228,10 @@ switch ($_REQUEST['action']) {
|
|||
$catalog->format();
|
||||
require_once AmpConfig::get('prefix') . '/templates/show_edit_catalog.inc.php';
|
||||
break;
|
||||
case 'gather_album_art':
|
||||
toggle_visible('ajax-loading');
|
||||
ob_end_flush();
|
||||
|
||||
$catalogs = $_REQUEST['catalogs'] ? $_REQUEST['catalogs'] : Catalog::get_catalogs();
|
||||
|
||||
// Iterate throught the catalogs and gather as needed
|
||||
foreach ($catalogs as $catalog_id) {
|
||||
$catalog = Catalog::create_from_id($catalog_id);
|
||||
require AmpConfig::get('prefix') . '/templates/show_gather_art.inc.php';
|
||||
flush();
|
||||
$catalog->gather_art();
|
||||
}
|
||||
$url = AmpConfig::get('web_path') . '/admin/catalog.php';
|
||||
$title = T_('Album Art Search Finished');
|
||||
$body = '';
|
||||
show_confirmation($title,$body,$url);
|
||||
case 'gather_media_art':
|
||||
$sse_url = AmpConfig::get('web_path') . "/server/sse.server.php?worker=catalog&action=gather_media_art&catalogs=" . $sse_catalogs;
|
||||
sse_worker($sse_url);
|
||||
show_confirmation(T_('Media Art Search started...'), '', AmpConfig::get('web_path') . '/admin/catalog.php', 0, 'confirmation', false);
|
||||
break;
|
||||
case 'show_catalogs':
|
||||
default:
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
|
65
sources/admin/license.php
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
|
||||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
require_once '../lib/init.php';
|
||||
|
||||
if (!Access::check('interface','100')) {
|
||||
UI::access_denied();
|
||||
exit;
|
||||
}
|
||||
|
||||
UI::show_header();
|
||||
|
||||
switch ($_REQUEST['action']) {
|
||||
case 'edit':
|
||||
if (isset($_POST['license_id'])) {
|
||||
$license = new License($_POST['license_id']);
|
||||
if ($license->id) {
|
||||
$license->update($_POST);
|
||||
}
|
||||
$text = T_('License Updated');
|
||||
} else {
|
||||
License::create($_POST);
|
||||
$text = T_('License Created');
|
||||
}
|
||||
show_confirmation($text,'',AmpConfig::get('web_path').'/admin/license.php');
|
||||
break;
|
||||
case 'show_edit':
|
||||
$license = new License($_REQUEST['license_id']);
|
||||
case 'show_create':
|
||||
require_once AmpConfig::get('prefix') . '/templates/show_edit_license.inc.php';
|
||||
break;
|
||||
case 'delete':
|
||||
License::delete($_REQUEST['license_id']);
|
||||
show_confirmation(T_('License Deleted'),'',AmpConfig::get('web_path').'/admin/license.php');
|
||||
break;
|
||||
default:
|
||||
$browse = new Browse();
|
||||
$browse->set_type('license');
|
||||
$browse->set_simple_browse(true);
|
||||
$license_ids = $browse->get_objects();
|
||||
$browse->show_objects($license_ids);
|
||||
$browse->store();
|
||||
break;
|
||||
}
|
||||
|
||||
UI::show_footer();
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -39,7 +39,10 @@ switch ($_REQUEST['action']) {
|
|||
|
||||
// Multi-byte Character Mail
|
||||
if (function_exists('mb_language')) {
|
||||
ini_set("mbstring.internal_encoding","UTF-8");
|
||||
$ini_default_charset = version_compare(PHP_VERSION, '5.6', '<') ? 'mbstring.internal_encoding' : 'default_charset';
|
||||
if (ini_get($ini_default_charset)) {
|
||||
ini_set($ini_default_charset, "UTF-8");
|
||||
}
|
||||
mb_language("uni");
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -48,10 +48,14 @@ switch ($_REQUEST['action']) {
|
|||
Preference::update('localplay_level',$GLOBALS['user']->id,'100');
|
||||
Preference::update('localplay_controller',$GLOBALS['user']->id,$localplay->type);
|
||||
|
||||
header("Location:" . AmpConfig::get('web_path') . '/admin/modules.php?action=show_localplay');
|
||||
/* Show Confirmation */
|
||||
$url = AmpConfig::get('web_path') . '/admin/modules.php?action=show_localplay';
|
||||
$title = T_('Localplay Installed');
|
||||
$body = '';
|
||||
show_confirmation($title ,$body, $url);
|
||||
break;
|
||||
case 'install_catalog_type':
|
||||
$type = scrub_in($_REQUEST['type']);
|
||||
$type = (string) scrub_in($_REQUEST['type']);
|
||||
$catalog = Catalog::create_catalog_type($type);
|
||||
if ($catalog == null) {
|
||||
Error::add('general', T_('Install Failed, Catalog Error'));
|
||||
|
@ -68,21 +72,21 @@ switch ($_REQUEST['action']) {
|
|||
show_confirmation($title ,$body, $url);
|
||||
break;
|
||||
case 'confirm_uninstall_localplay':
|
||||
$type = scrub_in($_REQUEST['type']);
|
||||
$type = (string) scrub_in($_REQUEST['type']);
|
||||
$url = AmpConfig::get('web_path') . '/admin/modules.php?action=uninstall_localplay&type=' . $type;
|
||||
$title = T_('Are you sure you want to remove this plugin?');
|
||||
$body = '';
|
||||
show_confirmation($title,$body,$url,1);
|
||||
break;
|
||||
case 'confirm_uninstall_catalog_type':
|
||||
$type = scrub_in($_REQUEST['type']);
|
||||
$type = (string) scrub_in($_REQUEST['type']);
|
||||
$url = AmpConfig::get('web_path') . '/admin/modules.php?action=uninstall_catalog_type&type=' . $type;
|
||||
$title = T_('Are you sure you want to remove this plugin?');
|
||||
$body = '';
|
||||
show_confirmation($title,$body,$url,1);
|
||||
break;
|
||||
case 'uninstall_localplay':
|
||||
$type = scrub_in($_REQUEST['type']);
|
||||
$type = (string) scrub_in($_REQUEST['type']);
|
||||
|
||||
$localplay = new Localplay($type);
|
||||
$localplay->uninstall();
|
||||
|
@ -94,7 +98,7 @@ switch ($_REQUEST['action']) {
|
|||
show_confirmation($title,$body,$url);
|
||||
break;
|
||||
case 'uninstall_catalog_type':
|
||||
$type = scrub_in($_REQUEST['type']);
|
||||
$type = (string) scrub_in($_REQUEST['type']);
|
||||
|
||||
$catalog = Catalog::create_catalog_type($type);
|
||||
if ($catalog == null) {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -32,8 +32,10 @@ UI::show_header();
|
|||
// Switch on the incomming action
|
||||
switch ($_REQUEST['action']) {
|
||||
case 'edit_shout':
|
||||
$shout_id = $_POST['shout_id'];
|
||||
$update = Shoutbox::update($_POST);
|
||||
$shout = new Shoutbox($_REQUEST['shout_id']);
|
||||
if ($shout->id) {
|
||||
$shout->update($_POST);
|
||||
}
|
||||
show_confirmation(T_('Shoutbox Post Updated'),'',AmpConfig::get('web_path').'/admin/shout.php');
|
||||
break;
|
||||
case 'show_edit':
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -39,9 +39,13 @@ switch ($_REQUEST['action']) {
|
|||
$current = parse_ini_file(AmpConfig::get('prefix') . '/config/ampache.cfg.php');
|
||||
$final = generate_config($current);
|
||||
$browser = new Horde_Browser();
|
||||
$browser->downloadHeaders('ampache.cfg.php','text/plain',false,filesize(AmpConfig::get('prefix') . '/config/ampache.cfg.php.dist'));
|
||||
$browser->downloadHeaders('ampache.cfg.php', 'text/plain',false,filesize(AmpConfig::get('prefix') . '/config/ampache.cfg.php.dist'));
|
||||
echo $final;
|
||||
exit;
|
||||
case 'write_config':
|
||||
write_config(AmpConfig::get('prefix') . '/config/ampache.cfg.php');
|
||||
header('Location: '. AmpConfig::get('web_path') . '/index.php');
|
||||
exit;
|
||||
case 'reset_db_charset':
|
||||
Dba::reset_db_charset();
|
||||
show_confirmation(T_('Database Charset Updated'), T_('Your Database and associated tables have been updated to match your currently configured charset'), AmpConfig::get('web_path').'/admin/system.php?action=show_debug');
|
||||
|
@ -53,6 +57,14 @@ switch ($_REQUEST['action']) {
|
|||
}
|
||||
require_once AmpConfig::get('prefix') . '/templates/show_debug.inc.php';
|
||||
break;
|
||||
case 'clear_cache':
|
||||
switch ($_REQUEST['type']) {
|
||||
case 'song' : Song::clear_cache(); break;
|
||||
case 'artist' : Artist::clear_cache(); break;
|
||||
case 'album' : Album::clear_cache(); break;
|
||||
}
|
||||
show_confirmation(T_('Cache cleared'), T_('Your cache has been cleared successfully.'), AmpConfig::get('web_path').'/admin/system.php?action=show_debug');
|
||||
break;
|
||||
default:
|
||||
// Rien a faire
|
||||
break;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -40,14 +40,17 @@ switch ($_REQUEST['action']) {
|
|||
}
|
||||
|
||||
/* Clean up the variables */
|
||||
$user_id = intval($_POST['user_id']);
|
||||
$username = scrub_in($_POST['username']);
|
||||
$fullname = scrub_in($_POST['fullname']);
|
||||
$email = scrub_in($_POST['email']);
|
||||
$website = scrub_in($_POST['website']);
|
||||
$access = scrub_in($_POST['access']);
|
||||
$pass1 = $_POST['password_1'];
|
||||
$pass2 = $_POST['password_2'];
|
||||
$user_id = intval($_POST['user_id']);
|
||||
$username = scrub_in($_POST['username']);
|
||||
$fullname = scrub_in($_POST['fullname']);
|
||||
$email = scrub_in($_POST['email']);
|
||||
$website = scrub_in($_POST['website']);
|
||||
$access = scrub_in($_POST['access']);
|
||||
$pass1 = $_POST['password_1'];
|
||||
$pass2 = $_POST['password_2'];
|
||||
$state = scrub_in($_POST['state']);
|
||||
$city = scrub_in($_POST['city']);
|
||||
$fullname_public = isset($_POST['fullname_public']);
|
||||
|
||||
/* Setup the temp user */
|
||||
$client = new User($user_id);
|
||||
|
@ -55,16 +58,27 @@ switch ($_REQUEST['action']) {
|
|||
/* Verify Input */
|
||||
if (empty($username)) {
|
||||
Error::add('username', T_("Error Username Required"));
|
||||
} else {
|
||||
if ($username != $client->username) {
|
||||
if (!User::check_username($username)) {
|
||||
Error::add('username', T_("Error Username already exists"));
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($pass1 !== $pass2 && !empty($pass1)) {
|
||||
Error::add('password', T_("Error Passwords don't match"));
|
||||
}
|
||||
|
||||
/* If we've got an error then break! */
|
||||
// Check the mail for correct address formation.
|
||||
if (!Mailer::validate_address($email)) {
|
||||
Error::add('email', T_('Invalid email address'));
|
||||
}
|
||||
|
||||
/* If we've got an error then show edit form! */
|
||||
if (Error::occurred()) {
|
||||
$_REQUEST['action'] = 'show_edit';
|
||||
require_once AmpConfig::get('prefix') . '/templates/show_edit_user.inc.php';
|
||||
break;
|
||||
} // if we've had an oops!
|
||||
}
|
||||
|
||||
if ($access != $client->access) {
|
||||
$client->update_access($access);
|
||||
|
@ -81,9 +95,18 @@ switch ($_REQUEST['action']) {
|
|||
if ($fullname != $client->fullname) {
|
||||
$client->update_fullname($fullname);
|
||||
}
|
||||
if ($fullname_public != $client->fullname_public) {
|
||||
$client->update_fullname_public($fullname_public);
|
||||
}
|
||||
if ($pass1 == $pass2 && strlen($pass1)) {
|
||||
$client->update_password($pass1);
|
||||
}
|
||||
if ($state != $client->state) {
|
||||
$client->update_state($state);
|
||||
}
|
||||
if ($city != $client->city) {
|
||||
$client->update_city($city);
|
||||
}
|
||||
$client->upload_avatar();
|
||||
|
||||
show_confirmation(T_('User Updated'), $client->fullname . "(" . $client->username . ")" . T_('updated'), AmpConfig::get('web_path'). '/admin/users.php');
|
||||
|
@ -96,13 +119,15 @@ switch ($_REQUEST['action']) {
|
|||
exit;
|
||||
}
|
||||
|
||||
$username = scrub_in($_POST['username']);
|
||||
$fullname = scrub_in($_POST['fullname']);
|
||||
$email = scrub_in($_POST['email']);
|
||||
$username = scrub_in($_POST['username']);
|
||||
$fullname = scrub_in($_POST['fullname']);
|
||||
$email = scrub_in($_POST['email']);
|
||||
$website = scrub_in($_POST['website']);
|
||||
$access = scrub_in($_POST['access']);
|
||||
$pass1 = $_POST['password_1'];
|
||||
$pass2 = $_POST['password_2'];
|
||||
$access = scrub_in($_POST['access']);
|
||||
$pass1 = $_POST['password_1'];
|
||||
$pass2 = $_POST['password_2'];
|
||||
$state = (string) scrub_in($_POST['state']);
|
||||
$city = (string) scrub_in($_POST['city']);
|
||||
|
||||
if ($pass1 !== $pass2 || !strlen($pass1)) {
|
||||
Error::add('password', T_("Error Passwords don't match"));
|
||||
|
@ -117,20 +142,25 @@ switch ($_REQUEST['action']) {
|
|||
Error::add('username', T_('Error Username already exists'));
|
||||
}
|
||||
|
||||
if (!Error::occurred()) {
|
||||
/* Attempt to create the user */
|
||||
$user_id = User::create($username, $fullname, $email, $website, $pass1, $access);
|
||||
if (!$user_id) {
|
||||
Error::add('general', T_("Error: Insert Failed"));
|
||||
}
|
||||
// Check the mail for correct address formation.
|
||||
if (!Mailer::validate_address($email)) {
|
||||
Error::add('email', T_('Invalid email address'));
|
||||
}
|
||||
|
||||
$user = new User($user_id);
|
||||
$user->upload_avatar();
|
||||
} // if no errors
|
||||
else {
|
||||
$_REQUEST['action'] = 'show_add_user';
|
||||
/* If we've got an error then show add form! */
|
||||
if (Error::occurred()) {
|
||||
require_once AmpConfig::get('prefix') . '/templates/show_add_user.inc.php';
|
||||
break;
|
||||
}
|
||||
|
||||
/* Attempt to create the user */
|
||||
$user_id = User::create($username, $fullname, $email, $website, $pass1, $access, $state, $city);
|
||||
if (!$user_id) {
|
||||
Error::add('general', T_("Error: Insert Failed"));
|
||||
}
|
||||
$user = new User($user_id);
|
||||
$user->upload_avatar();
|
||||
|
||||
if ($access == 5) { $access = T_('Guest');} elseif ($access == 25) { $access = T_('User');} elseif ($access == 100) { $access = T_('Admin');}
|
||||
|
||||
/* HINT: %1 Username, %2 Access num */
|
||||
|
@ -139,6 +169,9 @@ switch ($_REQUEST['action']) {
|
|||
case 'enable':
|
||||
$client = new User($_REQUEST['user_id']);
|
||||
$client->enable();
|
||||
if (!AmpConfig::get('user_no_email_confirm')) {
|
||||
Registration::send_account_enabled($client->username, $client->fullname, $client->email);
|
||||
}
|
||||
show_confirmation(T_('User Enabled'),$client->fullname . ' (' . $client->username . ')', AmpConfig::get('web_path'). '/admin/users.php');
|
||||
break;
|
||||
case 'disable':
|
||||
|
@ -239,7 +272,7 @@ switch ($_REQUEST['action']) {
|
|||
$browse = new Browse();
|
||||
$browse->reset_filters();
|
||||
$browse->set_type('user');
|
||||
$browse->set_simple_browse(1);
|
||||
$browse->set_simple_browse(true);
|
||||
$browse->set_sort('name','ASC');
|
||||
$user_ids = $browse->get_objects();
|
||||
$browse->show_objects($user_ids);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -26,144 +26,33 @@ require_once AmpConfig::get('prefix') . '/templates/header.inc.php';
|
|||
|
||||
/* Switch on Action */
|
||||
switch ($_REQUEST['action']) {
|
||||
case 'clear_art':
|
||||
if (!$GLOBALS['user']->has_access('75')) { UI::access_denied(); }
|
||||
$art = new Art($_GET['album_id'],'album');
|
||||
$art->reset();
|
||||
show_confirmation(T_('Album Art Cleared'), T_('Album Art information has been removed from the database'),"/albums.php?action=show&album=" . $art->uid);
|
||||
break;
|
||||
// Upload album art
|
||||
case 'upload_art':
|
||||
case 'delete':
|
||||
if (AmpConfig::get('demo_mode')) { break; }
|
||||
|
||||
// we didn't find anything
|
||||
if (empty($_FILES['file']['tmp_name'])) {
|
||||
show_confirmation(T_('Album Art Not Located'), T_('Album Art could not be located at this time. This may be due to write access error, or the file is not received correctly.'),"/albums.php?action=show&album=" . $_REQUEST['album_id']);
|
||||
break;
|
||||
}
|
||||
$album_id = scrub_in($_REQUEST['album_id']);
|
||||
show_confirmation(
|
||||
T_('Album Deletion'),
|
||||
T_('Are you sure you want to permanently delete this album?'),
|
||||
AmpConfig::get('web_path')."/albums.php?action=confirm_delete&album_id=" . $album_id,
|
||||
1,
|
||||
'delete_album'
|
||||
);
|
||||
break;
|
||||
case 'confirm_delete':
|
||||
if (AmpConfig::get('demo_mode')) { break; }
|
||||
|
||||
$album = new Album($_REQUEST['album_id']);
|
||||
// Pull the image information
|
||||
$data = array('file'=>$_FILES['file']['tmp_name']);
|
||||
$image_data = Art::get_from_source($data, 'album');
|
||||
|
||||
// If we got something back insert it
|
||||
if ($image_data) {
|
||||
$art = new Art($album->id,'album');
|
||||
$art->insert($image_data,$_FILES['file']['type']);
|
||||
show_confirmation(T_('Album Art Inserted'),'',"/albums.php?action=show&album=" . $album->id);
|
||||
}
|
||||
// Else it failed
|
||||
else {
|
||||
show_confirmation(T_('Album Art Not Located'), T_('Album Art could not be located at this time. This may be due to write access error, or the file is not received correctly.'),"/albums.php?action=show&album=" . $album->id);
|
||||
if (!Catalog::can_remove($album)) {
|
||||
debug_event('album', 'Unauthorized to remove the album `.' . $album->id . '`.', 1);
|
||||
UI::access_denied();
|
||||
exit;
|
||||
}
|
||||
|
||||
break;
|
||||
case 'find_art':
|
||||
// If not a user then kick em out
|
||||
if (!Access::check('interface','25')) { UI::access_denied(); exit; }
|
||||
|
||||
// Prevent the script from timing out
|
||||
set_time_limit(0);
|
||||
|
||||
// get the Album information
|
||||
$album = new Album($_GET['album_id']);
|
||||
$album->format();
|
||||
$art = new Art($album->id,'album');
|
||||
$images = array();
|
||||
$cover_url = array();
|
||||
|
||||
// If we've got an upload ignore the rest and just insert it
|
||||
if (!empty($_FILES['file']['tmp_name'])) {
|
||||
$path_info = pathinfo($_FILES['file']['name']);
|
||||
$upload['file'] = $_FILES['file']['tmp_name'];
|
||||
$upload['mime'] = 'image/' . $path_info['extension'];
|
||||
$image_data = Art::get_from_source($upload, 'album');
|
||||
|
||||
if ($image_data) {
|
||||
$art->insert($image_data,$upload['0']['mime']);
|
||||
show_confirmation(T_('Album Art Inserted'),'',"/albums.php?action=show&album=" . $_REQUEST['album_id']);
|
||||
break;
|
||||
|
||||
} // if image data
|
||||
|
||||
} // if it's an upload
|
||||
|
||||
// Build the options for our search
|
||||
if (isset($_REQUEST['artist_name'])) {
|
||||
$artist = scrub_in($_REQUEST['artist_name']);
|
||||
} elseif ($album->artist_count == '1') {
|
||||
$artist = $album->f_artist_name;
|
||||
if ($album->remove_from_disk()) {
|
||||
show_confirmation(T_('Album Deletion'), T_('Album has been deleted.'), AmpConfig::get('web_path'));
|
||||
} else {
|
||||
$artist = "";
|
||||
show_confirmation(T_('Album Deletion'), T_('Cannot delete this album.'), AmpConfig::get('web_path'));
|
||||
}
|
||||
if (isset($_REQUEST['album_name'])) {
|
||||
$album_name = scrub_in($_REQUEST['album_name']);
|
||||
} else {
|
||||
$album_name = $album->full_name;
|
||||
}
|
||||
|
||||
$options['artist'] = $artist;
|
||||
$options['album_name'] = $album_name;
|
||||
$options['keyword'] = trim($artist . " " . $album_name);
|
||||
|
||||
// Attempt to find the art.
|
||||
$images = $art->gather($options);
|
||||
|
||||
if (!empty($_REQUEST['cover'])) {
|
||||
$path_info = pathinfo($_REQUEST['cover']);
|
||||
$cover_url[0]['url'] = scrub_in($_REQUEST['cover']);
|
||||
$cover_url[0]['mime'] = 'image/' . $path_info['extension'];
|
||||
}
|
||||
$images = array_merge($cover_url,$images);
|
||||
|
||||
// If we've found anything then go for it!
|
||||
if (count($images)) {
|
||||
// We don't want to store raw's in here so we need to strip them out into a separate array
|
||||
foreach ($images as $index=>$image) {
|
||||
if ($image['raw']) {
|
||||
unset($images[$index]['raw']);
|
||||
}
|
||||
} // end foreach
|
||||
// Store the results for further use
|
||||
$_SESSION['form']['images'] = $images;
|
||||
require_once AmpConfig::get('prefix') . '/templates/show_album_art.inc.php';
|
||||
}
|
||||
// Else nothing
|
||||
else {
|
||||
show_confirmation(T_('Album Art Not Located'), T_('Album Art could not be located at this time. This may be due to write access error, or the file is not received correctly.'),"/albums.php?action=show&album=" . $album->id);
|
||||
}
|
||||
|
||||
$albumname = $album->name;
|
||||
$artistname = $artist;
|
||||
|
||||
// Remember the last typed entry, if there was one
|
||||
if (!empty($_REQUEST['album_name'])) { $albumname = scrub_in($_REQUEST['album_name']); }
|
||||
if (!empty($_REQUEST['artist_name'])) { $artistname = scrub_in($_REQUEST['artist_name']); }
|
||||
|
||||
require_once AmpConfig::get('prefix') . '/templates/show_get_albumart.inc.php';
|
||||
|
||||
break;
|
||||
case 'select_art':
|
||||
|
||||
/* Check to see if we have the image url still */
|
||||
$image_id = $_REQUEST['image'];
|
||||
$album_id = $_REQUEST['album_id'];
|
||||
|
||||
// Prevent the script from timing out
|
||||
set_time_limit(0);
|
||||
|
||||
$album = new Album($album_id);
|
||||
$album_groups = $album->get_group_disks_ids();
|
||||
|
||||
$image = Art::get_from_source($_SESSION['form']['images'][$image_id], 'album');
|
||||
$mime = $_SESSION['form']['images'][$image_id]['mime'];
|
||||
|
||||
foreach ($album_groups as $a_id) {
|
||||
$art = new Art($a_id, 'album');
|
||||
$art->insert($image, $mime);
|
||||
}
|
||||
|
||||
header("Location:" . AmpConfig::get('web_path') . "/albums.php?action=show&album=" . $album_id);
|
||||
break;
|
||||
case 'update_from_tags':
|
||||
// Make sure they are a 'power' user at least
|
||||
|
@ -193,7 +82,7 @@ switch ($_REQUEST['action']) {
|
|||
|
||||
if (isset($_GET['order'])) {
|
||||
$songs = explode(";", $_GET['order']);
|
||||
$track = 1;
|
||||
$track = $_GET['offset'] ? (intval($_GET['offset']) + 1) : 1;
|
||||
foreach ($songs as $song_id) {
|
||||
if ($song_id != '') {
|
||||
Song::update_track($track, $song_id);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -28,10 +28,42 @@ UI::show_header();
|
|||
* Display Switch
|
||||
*/
|
||||
switch ($_REQUEST['action']) {
|
||||
case 'delete':
|
||||
if (AmpConfig::get('demo_mode')) { break; }
|
||||
|
||||
$artist_id = scrub_in($_REQUEST['artist_id']);
|
||||
show_confirmation(
|
||||
T_('Artist Deletion'),
|
||||
T_('Are you sure you want to permanently delete this artist?'),
|
||||
AmpConfig::get('web_path')."/artists.php?action=confirm_delete&artist_id=" . $artist_id,
|
||||
1,
|
||||
'delete_artist'
|
||||
);
|
||||
break;
|
||||
case 'confirm_delete':
|
||||
if (AmpConfig::get('demo_mode')) { break; }
|
||||
|
||||
$artist = new Artist($_REQUEST['artist_id']);
|
||||
if (!Catalog::can_remove($artist)) {
|
||||
debug_event('artist', 'Unauthorized to remove the artist `.' . $artist->id . '`.', 1);
|
||||
UI::access_denied();
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($artist->remove_from_disk()) {
|
||||
show_confirmation(T_('Artist Deletion'), T_('Artist has been deleted.'), AmpConfig::get('web_path'));
|
||||
} else {
|
||||
show_confirmation(T_('Artist Deletion'), T_('Cannot delete this artist.'), AmpConfig::get('web_path'));
|
||||
}
|
||||
break;
|
||||
case 'show':
|
||||
$artist = new Artist($_REQUEST['artist']);
|
||||
$artist->format();
|
||||
$object_ids = $artist->get_albums($_REQUEST['catalog']);
|
||||
if (AmpConfig::get('album_release_type')) {
|
||||
$multi_object_ids = $artist->get_albums($_REQUEST['catalog'], false, true);
|
||||
} else {
|
||||
$object_ids = $artist->get_albums($_REQUEST['catalog']);
|
||||
}
|
||||
$object_type = 'album';
|
||||
require_once AmpConfig::get('prefix') . '/templates/show_artist.inc.php';
|
||||
break;
|
||||
|
|
169
sources/arts.php
Normal file
|
@ -0,0 +1,169 @@
|
|||
<?php
|
||||
/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
|
||||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
require_once 'lib/init.php';
|
||||
|
||||
require_once AmpConfig::get('prefix') . '/templates/header.inc.php';
|
||||
|
||||
$object_type = $_GET['object_type'];
|
||||
$object_id = $_GET['object_id'];
|
||||
if (!Core::is_library_item($object_type)) { UI::access_denied(); exit; }
|
||||
$burl = '';
|
||||
if (isset($_GET['burl'])) {
|
||||
$burl = base64_decode($_GET['burl']);
|
||||
}
|
||||
$item = new $object_type($object_id);
|
||||
|
||||
// If not a content manager user then kick em out
|
||||
if (!Access::check('interface', 50) && (!Access::check('interface', 25) || $item->get_user_owner() != $GLOBALS['user']->id)) { UI::access_denied(); exit; }
|
||||
|
||||
/* Switch on Action */
|
||||
switch ($_REQUEST['action']) {
|
||||
case 'clear_art':
|
||||
$art = new Art($object_id, $object_type);
|
||||
$art->reset();
|
||||
show_confirmation(T_('Art Cleared'), T_('Art information has been removed from the database'), $burl);
|
||||
break;
|
||||
// Upload art
|
||||
case 'upload_art':
|
||||
// we didn't find anything
|
||||
if (empty($_FILES['file']['tmp_name'])) {
|
||||
show_confirmation(T_('Art Not Located'), T_('Art could not be located at this time. This may be due to write access error, or the file is not received correctly.'), $burl);
|
||||
break;
|
||||
}
|
||||
|
||||
// Pull the image information
|
||||
$data = array('file'=>$_FILES['file']['tmp_name']);
|
||||
$image_data = Art::get_from_source($data, $object_type);
|
||||
|
||||
// If we got something back insert it
|
||||
if ($image_data) {
|
||||
$art = new Art($object_id, $object_type);
|
||||
$art->insert($image_data,$_FILES['file']['type']);
|
||||
show_confirmation(T_('Art Inserted'), '', $burl);
|
||||
}
|
||||
// Else it failed
|
||||
else {
|
||||
show_confirmation(T_('Art Not Located'), T_('Art could not be located at this time. This may be due to write access error, or the file is not received correctly.'), $burl);
|
||||
}
|
||||
|
||||
break;
|
||||
case 'find_art':
|
||||
// Prevent the script from timing out
|
||||
set_time_limit(0);
|
||||
|
||||
$item->format();
|
||||
$art = new Art($object_id, $object_type);
|
||||
$images = array();
|
||||
$cover_url = array();
|
||||
|
||||
// If we've got an upload ignore the rest and just insert it
|
||||
if (!empty($_FILES['file']['tmp_name'])) {
|
||||
$path_info = pathinfo($_FILES['file']['name']);
|
||||
$upload['file'] = $_FILES['file']['tmp_name'];
|
||||
$upload['mime'] = 'image/' . $path_info['extension'];
|
||||
$image_data = Art::get_from_source($upload, $object_type);
|
||||
|
||||
if ($image_data) {
|
||||
$art->insert($image_data,$upload['0']['mime']);
|
||||
show_confirmation(T_('Art Inserted'), '', $burl);
|
||||
break;
|
||||
|
||||
} // if image data
|
||||
|
||||
} // if it's an upload
|
||||
|
||||
$keywords = $item->get_keywords();
|
||||
$keyword = '';
|
||||
$options = array();
|
||||
foreach ($keywords as $key => $word) {
|
||||
if (isset($_REQUEST['option_' . $key])) {
|
||||
$word['value'] = $_REQUEST['option_' . $key];
|
||||
}
|
||||
$options[$key] = $word['value'];
|
||||
if ($word['important']) {
|
||||
if (!empty($word['value'])) {
|
||||
$keyword .= ' ' . $word['value'];
|
||||
}
|
||||
}
|
||||
}
|
||||
$options['keyword'] = trim($keyword);
|
||||
|
||||
// Attempt to find the art.
|
||||
$images = $art->gather($options);
|
||||
|
||||
if (!empty($_REQUEST['cover'])) {
|
||||
$path_info = pathinfo($_REQUEST['cover']);
|
||||
$cover_url[0]['url'] = scrub_in($_REQUEST['cover']);
|
||||
$cover_url[0]['mime'] = 'image/' . $path_info['extension'];
|
||||
}
|
||||
$images = array_merge($cover_url, $images);
|
||||
|
||||
// If we've found anything then go for it!
|
||||
if (count($images)) {
|
||||
// We don't want to store raw's in here so we need to strip them out into a separate array
|
||||
foreach ($images as $index=>$image) {
|
||||
if ($image['raw']) {
|
||||
unset($images[$index]['raw']);
|
||||
}
|
||||
} // end foreach
|
||||
// Store the results for further use
|
||||
$_SESSION['form']['images'] = $images;
|
||||
require_once AmpConfig::get('prefix') . '/templates/show_arts.inc.php';
|
||||
}
|
||||
// Else nothing
|
||||
else {
|
||||
show_confirmation(T_('Art Not Located'), T_('Art could not be located at this time. This may be due to write access error, or the file is not received correctly.'), $burl);
|
||||
}
|
||||
|
||||
require_once AmpConfig::get('prefix') . '/templates/show_get_art.inc.php';
|
||||
|
||||
break;
|
||||
case 'select_art':
|
||||
|
||||
/* Check to see if we have the image url still */
|
||||
$image_id = $_REQUEST['image'];
|
||||
|
||||
// Prevent the script from timing out
|
||||
set_time_limit(0);
|
||||
|
||||
$image = Art::get_from_source($_SESSION['form']['images'][$image_id], 'album');
|
||||
$mime = $_SESSION['form']['images'][$image_id]['mime'];
|
||||
|
||||
// Special case for albums, I'm not sure if we should keep it, remove it or find a generic way
|
||||
if ($object_type == 'album') {
|
||||
$album = new $object_type($object_id);
|
||||
$album_groups = $album->get_group_disks_ids();
|
||||
foreach ($album_groups as $a_id) {
|
||||
$art = new Art($a_id, $object_type);
|
||||
$art->insert($image, $mime);
|
||||
}
|
||||
} else {
|
||||
$art = new Art($object_id, $object_type);
|
||||
$art->insert($image, $mime);
|
||||
}
|
||||
|
||||
header("Location:" . $burl);
|
||||
break;
|
||||
}
|
||||
|
||||
UI::show_footer();
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -21,7 +21,16 @@
|
|||
*/
|
||||
|
||||
if (!defined('NO_SESSION')) {
|
||||
require_once 'lib/init.php';
|
||||
if (isset($_REQUEST['ssid'])) {
|
||||
define('NO_SESSION', 1);
|
||||
require_once 'lib/init.php';
|
||||
if (!Session::exists('stream', $_REQUEST['ssid'])) {
|
||||
UI::access_denied();
|
||||
exit;
|
||||
}
|
||||
} else {
|
||||
require_once 'lib/init.php';
|
||||
}
|
||||
}
|
||||
|
||||
ob_end_clean();
|
||||
|
@ -35,72 +44,78 @@ if (!defined('NO_SESSION') && !Access::check_function('batch_download')) {
|
|||
set_time_limit(0);
|
||||
|
||||
$media_ids = array();
|
||||
$name = "Unknown.zip";
|
||||
$default_name = "Unknown.zip";
|
||||
$object_type = scrub_in($_REQUEST['action']);
|
||||
$name = $default_name;
|
||||
|
||||
switch ($_REQUEST['action']) {
|
||||
case 'tmp_playlist':
|
||||
$media_ids = $GLOBALS['user']->playlist->get_items();
|
||||
$name = $GLOBALS['user']->username . ' - Playlist';
|
||||
break;
|
||||
case 'playlist':
|
||||
$playlist = new Playlist($_REQUEST['id']);
|
||||
$media_ids = $playlist->get_songs();
|
||||
$name = $playlist->name;
|
||||
break;
|
||||
case 'smartplaylist':
|
||||
$search = new Search('song', $_REQUEST['id']);
|
||||
$sql = $search->to_sql();
|
||||
$sql = $sql['base'] . ' ' . $sql['table_sql'] . ' WHERE ' .
|
||||
$sql['where_sql'];
|
||||
$db_results = Dba::read($sql);
|
||||
while ($row = Dba::fetch_assoc($db_results)) {
|
||||
$media_ids[] = $row['id'];
|
||||
if ($object_type == 'browse') {
|
||||
$object_type = $_REQUEST['type'];
|
||||
}
|
||||
|
||||
if (!check_can_zip($object_type)) {
|
||||
debug_event('batch', 'Object type `' . $object_type . '` is not allowed to be zipped.', 1);
|
||||
UI::access_denied();
|
||||
exit;
|
||||
}
|
||||
|
||||
if (Core::is_playable_item($_REQUEST['action'])) {
|
||||
$id = $_REQUEST['id'];
|
||||
if (!is_array($id)) {
|
||||
$id = array($id);
|
||||
}
|
||||
$media_ids = array();
|
||||
foreach ($id as $i) {
|
||||
$libitem = new $object_type($i);
|
||||
if ($libitem->id) {
|
||||
$libitem->format();
|
||||
$name = $libitem->get_fullname();
|
||||
$media_ids = array_merge($media_ids, $libitem->get_medias());
|
||||
}
|
||||
$name = $search->name;
|
||||
break;
|
||||
case 'album':
|
||||
foreach ($_REQUEST['id'] as $a) {
|
||||
$album = new Album($a);
|
||||
if (empty($name)) {
|
||||
$name = $album->name;
|
||||
}
|
||||
$asongs = $album->get_songs();
|
||||
foreach ($asongs as $song_id) {
|
||||
$media_ids[] = $song_id;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'artist':
|
||||
$artist = new Artist($_REQUEST['id']);
|
||||
$media_ids = $artist->get_songs();
|
||||
$name = $artist->name;
|
||||
break;
|
||||
case 'browse':
|
||||
$id = scrub_in($_REQUEST['browse_id']);
|
||||
$browse = new Browse($id);
|
||||
$browse_media_ids = $browse->get_saved();
|
||||
foreach ($browse_media_ids as $media_id) {
|
||||
switch ($_REQUEST['type']) {
|
||||
case 'album':
|
||||
$album = new Album($media_id);
|
||||
$media_ids = array_merge($media_ids, $album->get_songs());
|
||||
break;
|
||||
case 'song':
|
||||
$media_ids[] = $media_id;
|
||||
break;
|
||||
case 'video':
|
||||
$media_ids[] = array('Video', $media_id);
|
||||
break;
|
||||
} // switch on type
|
||||
} // foreach media_id
|
||||
$name = 'Batch-' . date("dmY",time());
|
||||
default:
|
||||
// Rien a faire
|
||||
break;
|
||||
} // action switch
|
||||
}
|
||||
} else {
|
||||
switch ($_REQUEST['action']) {
|
||||
case 'tmp_playlist':
|
||||
$media_ids = $GLOBALS['user']->playlist->get_items();
|
||||
$name = $GLOBALS['user']->username . ' - Playlist';
|
||||
break;
|
||||
case 'browse':
|
||||
$id = intval(scrub_in($_REQUEST['browse_id']));
|
||||
$browse = new Browse($id);
|
||||
$browse_media_ids = $browse->get_saved();
|
||||
foreach ($browse_media_ids as $media_id) {
|
||||
switch ($object_type) {
|
||||
case 'album':
|
||||
$album = new Album($media_id);
|
||||
$media_ids = array_merge($media_ids, $album->get_songs());
|
||||
break;
|
||||
case 'song':
|
||||
$media_ids[] = $media_id;
|
||||
break;
|
||||
case 'video':
|
||||
$media_ids[] = array('object_type' => 'Video', 'object_id' => $media_id);
|
||||
break;
|
||||
} // switch on type
|
||||
} // foreach media_id
|
||||
$name = 'Batch-' . date("dmY",time());
|
||||
default:
|
||||
// Rien a faire
|
||||
break;
|
||||
} // action switch
|
||||
}
|
||||
|
||||
if (!User::stream_control($media_ids)) {
|
||||
debug_event('UI::access_denied', 'Stream control failed for user ' . $GLOBALS['user']->username, '3');
|
||||
UI::access_denied();
|
||||
exit;
|
||||
}
|
||||
|
||||
// Write/close session data to release session lock for this script.
|
||||
// This to allow other pages from the same session to be processed
|
||||
// Do NOT change any session variable after this call
|
||||
session_write_close();
|
||||
|
||||
// Take whatever we've got and send the zip
|
||||
$song_files = get_song_files($media_ids);
|
||||
$song_files = get_media_files($media_ids);
|
||||
if (is_array($song_files['0'])) {
|
||||
set_memory_limit($song_files['1']+32);
|
||||
send_zip($name,$song_files['0']);
|
||||
|
|
|
@ -1,2 +1,10 @@
|
|||
Order deny,allow
|
||||
Deny from all
|
||||
# Apache 2.4
|
||||
<IfModule mod_authz_core.c>
|
||||
Require all denied
|
||||
</IfModule>
|
||||
|
||||
# Apache 2.2
|
||||
<IfModule mod_access.c>
|
||||
Order deny,allow
|
||||
Deny from all
|
||||
</IfModule>
|
45
sources/bin/broadcast.inc
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
|
||||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
define('NO_SESSION','1');
|
||||
define('CLI', 1);
|
||||
|
||||
$path = dirname(__FILE__);
|
||||
$prefix = realpath($path . '/../');
|
||||
require_once $prefix . '/lib/init.php';
|
||||
|
||||
ob_end_flush();
|
||||
|
||||
echo T_("Starting broadcasts...") . "\n";
|
||||
|
||||
if (AmpConfig::get('upnp_backend')) {
|
||||
echo T_("UPnP broadcast... ");
|
||||
Upnp_Api::sddpSend();
|
||||
echo T_("Done.") . "\n";
|
||||
} else {
|
||||
echo T_("UPnP backend disabled. Broadcast skipped.") . "\n";
|
||||
}
|
||||
|
||||
ob_end_flush();
|
||||
echo "\n";
|
||||
|
||||
?>
|
48
sources/bin/calculate_art_size.inc
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
|
||||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
define('NO_SESSION','1');
|
||||
$path = dirname(__FILE__);
|
||||
$prefix = realpath($path . '/../');
|
||||
require_once $prefix . '/lib/init.php';
|
||||
|
||||
// Turn off output buffering we don't need it for a command line script
|
||||
ob_end_clean();
|
||||
|
||||
$sql = "SELECT `image`,`id` FROM `image`";
|
||||
$db_results = Dba::read($sql);
|
||||
$results = array();
|
||||
|
||||
while ($row = Dba::fetch_assoc($db_results)) {
|
||||
$source = $row['image'];
|
||||
$id = $row['id'];
|
||||
$dimensions = Core::image_dimensions($source);
|
||||
if ($dimensions) {
|
||||
$width = intval($dimensions['width']);
|
||||
$height = intval($dimensions['height']);
|
||||
$sql = "Update `image` SET `width`=". $width . ",`height`=".$height." WHERE `id`='".$id."'";
|
||||
Dba::write($sql);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -29,38 +29,48 @@ require_once $prefix . '/lib/init.php';
|
|||
|
||||
ob_end_flush();
|
||||
|
||||
$catclean = 0; //All off by default
|
||||
$tmpmemlimoff = 0; //All off by default
|
||||
$catclean = 0;
|
||||
$catverify = 0;
|
||||
$catadd = 0;
|
||||
$artadd = 0;
|
||||
$plimp = 0;
|
||||
$optimizetables = 0;
|
||||
|
||||
if (count($_SERVER['argv']) == 1) {
|
||||
$operations_string = "\n\t". T_('- All Catalog Operations');
|
||||
$operations_string = "\n\t- ". T_('Doing all catalog operations');
|
||||
}
|
||||
|
||||
if (count($_SERVER['argv']) > 1) {
|
||||
for ($x = 1; $x < count($_SERVER['argv']); $x++) {
|
||||
|
||||
if ($_SERVER['argv'][$x] == "-c") {
|
||||
$operations_string .= "\n\t" . T_('- Catalog Clean');
|
||||
if ($_SERVER['argv'][$x] == "-m") {
|
||||
$operations_string .= "\n\t- " . T_('Temporary deactivate PHP memory limit');
|
||||
$tmpmemlimoff = 1;
|
||||
}
|
||||
elseif ($_SERVER['argv'][$x] == "-c") {
|
||||
$operations_string .= "\n\t- " . T_('Cleaning catalog/s');
|
||||
$catclean = 1;
|
||||
}
|
||||
elseif ($_SERVER['argv'][$x] == "-v") {
|
||||
$operations_string .= "\n\t" . T_('- Catalog Verify');
|
||||
$operations_string .= "\n\t- " . T_('Verifying catalog/s');
|
||||
$catverify = 1;
|
||||
}
|
||||
elseif ($_SERVER['argv'][$x] == "-a") {
|
||||
$operations_string .= "\n\t" . T_('- Catalog Add');
|
||||
$operations_string .= "\n\t- " . T_('Adding new media to catalog/s');
|
||||
$catadd = 1;
|
||||
}
|
||||
elseif ($_SERVER['argv'][$x] == "-g") {
|
||||
$operations_string .= "\n\t" . T_('- Catalog Art Gather');
|
||||
$artadd = 1;
|
||||
$operations_string .= "\n\t- " . T_('Gathering new media art');
|
||||
$artadd = 1;
|
||||
}
|
||||
elseif ($_SERVER['argv'][$x] == "-i") {
|
||||
$operations_string .= "\n\t" . T_('- Playlist Import');
|
||||
$plimp = 1;
|
||||
$operations_string .= "\n\t- " . T_('Importing playlist/s');
|
||||
$plimp = 1;
|
||||
}
|
||||
elseif ($_SERVER['argv'][$x] == "-o") {
|
||||
$operations_string .= "\n\t- " . T_('Database table optimization');
|
||||
$optimizetables = 1;
|
||||
}
|
||||
else {
|
||||
if ($where) $where .= " OR ";
|
||||
|
@ -70,19 +80,43 @@ if (count($_SERVER['argv']) > 1) {
|
|||
}
|
||||
|
||||
if (count($_SERVER['argv']) != 1 AND $artadd != 1 && $catclean != 1 && $catverify != 1 && $catadd != 1) {
|
||||
usage();
|
||||
exit;
|
||||
usage();
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($artadd == 0 && $catclean == 0 && $catverify == 0 && $catadd == 0) { //didn't pass any clean/verify/add arguments
|
||||
$catclean = 1; //set them all to on
|
||||
if ($catclean == 0 && $catverify == 0 && $catadd == 0 && $artadd == 0 && $optimizetables == 0) { //didn't pass any clean/verify/add arguments
|
||||
$catclean = 1; //set them all to on
|
||||
$catverify = 1;
|
||||
$catadd = 1;
|
||||
$artadd = 1;
|
||||
$optimizetables = 1;
|
||||
}
|
||||
echo "\n----------------------------------------------------------\n";
|
||||
echo T_("Starting catalog operations...") . $operations_string . "\n";
|
||||
echo "----------------------------------------------------------\n\n";
|
||||
|
||||
// -------- Options before the catalog actions loop
|
||||
if ($tmpmemlimoff == 1) {
|
||||
// Temporarily deactivate PHP memory limit
|
||||
echo "\033[31m- " . T_("Deactivated PHP memory limit") . " -\033[0m\n";
|
||||
ini_set('memory_limit','-1');
|
||||
echo "------------------\n\n";
|
||||
}
|
||||
|
||||
echo T_("Starting Catalog Operations...") . $operations_string . "\n";
|
||||
|
||||
$options = array(); // for $catadd
|
||||
if ($artadd == 1) {
|
||||
echo "- " . T_("Gathering art") . " - \n";
|
||||
$options['gather_art'] = true;
|
||||
} else {
|
||||
$options['gather_art'] = false;
|
||||
}
|
||||
if ($plimp == 1) {
|
||||
echo "- " . T_("Parsing playlists") . " - \n";
|
||||
$options['parse_playlist'] = true;
|
||||
} else {
|
||||
$options['parse_playlist'] = false;
|
||||
}
|
||||
// --------
|
||||
if ($where) $where = "($where) AND catalog_type='local'";
|
||||
else $where = "catalog_type='local'";
|
||||
$sql = "SELECT id FROM catalog";
|
||||
|
@ -94,51 +128,49 @@ ob_start("ob_html_strip",'1024',true);
|
|||
while ($row = Dba::fetch_row($db_results)) {
|
||||
|
||||
$catalog = Catalog::create_from_id($row['0']);
|
||||
printf(T_('Reading: %s'), $catalog->name);
|
||||
ob_flush();
|
||||
echo "\n";
|
||||
printf(T_('Reading catalog: %s'), $catalog->name);
|
||||
ob_flush();
|
||||
echo "\n";
|
||||
|
||||
if ($catclean == 1) {
|
||||
// Clean out dead files
|
||||
echo T_("- Starting Clean - ");
|
||||
echo "- " . T_("Start cleaning orphaned media entries") . " - \n";
|
||||
echo "\n";
|
||||
$catalog->clean_catalog();
|
||||
echo "------------------\n\n";
|
||||
}
|
||||
|
||||
if ($catverify == 1) {
|
||||
// Verify Existing
|
||||
echo T_("- Starting Verify - ");
|
||||
echo "- " . T_("Start verifying media related to catalog entries") . " - \n";
|
||||
echo "\n";
|
||||
$catalog->verify_catalog($row['0']);
|
||||
echo "-------------------\n\n";
|
||||
}
|
||||
|
||||
if ($catadd == 1) {
|
||||
// Look for new files
|
||||
echo T_("- Starting Add - ");
|
||||
echo "- " . T_("Start adding new media") . " - \n";
|
||||
echo "\n";
|
||||
$options = array();
|
||||
if ($artadd == 1) {
|
||||
$options['gather_art'] = true;
|
||||
}
|
||||
if ($plimp == 1) {
|
||||
$options['parse_playlist'] = true;
|
||||
}
|
||||
$catalog->add_to_catalog($options);
|
||||
echo "----------------\n\n";
|
||||
} elseif ($artadd == 1) {
|
||||
// Look for album art
|
||||
echo T_('Starting Album Art Search');
|
||||
echo "\n";
|
||||
}
|
||||
elseif ($artadd == 1) {
|
||||
// Look for media art
|
||||
echo "- " . T_('Start searching new media art') . " - \n";
|
||||
echo "\n";
|
||||
$catalog->gather_art();
|
||||
echo "----------------\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($optimizetables == 1) {
|
||||
// Optimize Database Tables
|
||||
echo "- " . T_('Optimizing database tables') . " - \n";
|
||||
echo "\n";
|
||||
Dba::optimize_tables();
|
||||
echo "------------------\n\n";
|
||||
}
|
||||
|
||||
Dba::optimize_tables();
|
||||
|
||||
ob_end_flush();
|
||||
echo "\n";
|
||||
ob_end_flush();
|
||||
echo "\n";
|
||||
|
||||
function ob_html_strip($string) {
|
||||
|
||||
|
@ -154,22 +186,37 @@ function ob_html_strip($string) {
|
|||
} // ob_html_strip
|
||||
|
||||
function usage() {
|
||||
echo T_("- Catalog Update -");
|
||||
echo "\n";
|
||||
echo T_("Usage: catalog_update.inc [CATALOG NAME] [-c|-v|-a|-g|-t|-i]");
|
||||
echo "\n\t";
|
||||
echo T_("Default behavior is to do all except playlist import");
|
||||
echo "----------------------------------------------------------\n\t\t";
|
||||
echo T_("- Catalog Update Help -");
|
||||
echo "\n\033[32m";
|
||||
echo T_("Usage: catalog_update.inc [CATALOG NAME] [-m|-c|-v|-a|-g|-i|-o]") . "\033[0m (\033[31m!\033[0m)";
|
||||
echo "\033[0m\n";
|
||||
echo "----------------------------------------------------------";
|
||||
echo "\n";
|
||||
echo T_("Default behavior is to do all except temporarily deactivate the php memory limit");
|
||||
echo "\n";
|
||||
echo "----------------------------------------------------------";
|
||||
echo "\n-m\t";
|
||||
echo T_('Temporarily deactivates PHP memory limit.') . " (\033[31m1\033[0m)";
|
||||
echo "\n-c\t";
|
||||
echo T_('Clean Catalogs');
|
||||
echo T_('Cleans catalogs from orphaned entries.');
|
||||
echo "\n-v\t";
|
||||
echo T_('Verify Catalogs');
|
||||
echo T_('Verifies catalog entries and updates them if related files have new information.');
|
||||
echo "\n-a\t";
|
||||
echo T_('Add to Catalogs');
|
||||
echo "\n-i\t";
|
||||
echo T_('Import Playlists');
|
||||
echo T_('Adds new media to catalogs.');
|
||||
echo "\n-g\t";
|
||||
echo T_('Gather Art');
|
||||
echo T_('Gathers media Art.');
|
||||
echo "\n-i\t";
|
||||
echo T_('Imports playlists.');
|
||||
echo "\n-o\t";
|
||||
echo T_('Optimizes Database Tables.') . " (\033[31m2\033[0m)";
|
||||
echo "\n";
|
||||
echo "----------------------------------------------------------\033[31m\n";
|
||||
echo "1. " . T_('Use this option at your own risk! Your system could crash or become unresponsive due to huge memory consumption!') . "\n";
|
||||
echo "2. " . T_('Depending on your systems performance, this option could need a long time to finish and extremely slow down other database processes if you have big catalogs!') . "\n";
|
||||
echo "! " . T_('The switches [-m|-i|-o] can only be used, if one of the other switches [-c|-v|-a|-g] is used.');
|
||||
echo "\033[0m\n";
|
||||
echo "----------------------------------------------------------";
|
||||
echo "\n";
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -23,6 +23,8 @@
|
|||
define('NO_SESSION','1');
|
||||
define('CLI', 1);
|
||||
|
||||
$chunk_buffer = '';
|
||||
$nb_chunks_remainder = 0;
|
||||
$path = dirname(__FILE__);
|
||||
$prefix = realpath($path . '/../');
|
||||
require_once $prefix . '/lib/init.php';
|
||||
|
@ -42,11 +44,11 @@ if ($cargv > 1) {
|
|||
if ($_SERVER['argv'][$x] == "-c" && ($x + 1) < $cargv) {
|
||||
$chanid = intval($_SERVER['argv'][++$x]);
|
||||
$operations_string .= "\n\t" . T_('- Channel ' . $chanid);
|
||||
}
|
||||
}
|
||||
elseif ($_SERVER['argv'][$x] == "-v") {
|
||||
$operations_string .= "\n\t" . T_('- Verbose');
|
||||
$verbose = true;
|
||||
}
|
||||
}
|
||||
elseif ($_SERVER['argv'][$x] == "-p" && ($x + 1) < $cargv) {
|
||||
$port = intval($_SERVER['argv'][++$x]);
|
||||
$operations_string .= "\n\t" . T_('- Port ' . $port);
|
||||
|
@ -56,7 +58,7 @@ if ($cargv > 1) {
|
|||
|
||||
if ($chanid <= 0) {
|
||||
usage();
|
||||
exit;
|
||||
exit;
|
||||
}
|
||||
|
||||
// Transcode is mandatory to have consistent stream codec
|
||||
|
@ -66,7 +68,7 @@ if ($transcode_cfg == 'never') {
|
|||
die('Cannot start channel, transcoding is mandatory to work.');
|
||||
}
|
||||
|
||||
echo T_("Starting Channel...") . $operations_string . "\n";
|
||||
echo T_("Starting Channel...") . $operations_string . "\n";
|
||||
|
||||
$channel = new Channel($chanid);
|
||||
if (!$channel->id) {
|
||||
|
@ -106,7 +108,7 @@ echo T_("Listening on ") . $address . ':' . $port . "\n";
|
|||
|
||||
$stream_clients = array();
|
||||
$client_socks = array();
|
||||
$last_stream = 0;
|
||||
$last_stream = microtime(true);
|
||||
while(true)
|
||||
{
|
||||
//prepare readable sockets
|
||||
|
@ -114,7 +116,6 @@ while(true)
|
|||
if (count($client_socks) < $channel->max_listeners) {
|
||||
$read_socks[] = $server;
|
||||
}
|
||||
|
||||
//echo "b\n";ob_flush();
|
||||
//start reading and use a large timeout
|
||||
if(stream_select ( $read_socks, $write, $except, 1))
|
||||
|
@ -123,7 +124,7 @@ while(true)
|
|||
if (in_array($server, $read_socks))
|
||||
{
|
||||
$new_client = stream_socket_accept($server);
|
||||
|
||||
|
||||
if ($new_client)
|
||||
{
|
||||
debug_event('channel', 'Connection accepted from ' . stream_socket_get_name($new_client, true) . '.', '5');
|
||||
|
@ -133,288 +134,120 @@ while(true)
|
|||
echo "New client connected.\n";
|
||||
ob_flush();
|
||||
}
|
||||
|
||||
|
||||
//delete the server socket from the read sockets
|
||||
unset($read_socks[array_search($server, $read_socks)]);
|
||||
}
|
||||
|
||||
|
||||
// Get new message from existing client
|
||||
foreach($read_socks as $sock)
|
||||
{
|
||||
$data = fread($sock, 1024);
|
||||
if(!$data)
|
||||
{
|
||||
client_disconnect($channel, $client_socks, $stream_clients, $sock);
|
||||
continue;
|
||||
}
|
||||
|
||||
$headers = explode("\n", $data);
|
||||
|
||||
if (count($headers) > 0) {
|
||||
$cmd = explode(" ", $headers[0]);
|
||||
if ($cmd['0'] == 'GET') {
|
||||
switch ($cmd['1']) {
|
||||
case '/stream.' . $channel->stream_type:
|
||||
$options = array(
|
||||
'socket' => $sock,
|
||||
'length' => 0
|
||||
);
|
||||
|
||||
for ($i = 1; $i < count($headers); $i++) {
|
||||
$headerpart = explode(":", $headers[$i], 2);
|
||||
$header = strtolower(trim($headerpart[0]));
|
||||
$value = trim($headerpart[1]);
|
||||
switch ($header) {
|
||||
case 'icy-metadata':
|
||||
$options['metadata'] = ($value == '1');
|
||||
$options['metadata_lastsent'] = 0;
|
||||
$options['metadata_lastsong'] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Stream request
|
||||
if ($options['metadata']) {
|
||||
//fwrite($sock, "ICY 200 OK\r\n");
|
||||
fwrite($sock, "HTTP/1.0 200 OK\r\n");
|
||||
} else {
|
||||
fwrite($sock, "HTTP/1.1 200 OK\r\n");
|
||||
fwrite($sock, "Cache-Control: no-store, no-cache, must-revalidate\r\n");
|
||||
}
|
||||
fwrite($sock, "Content-Type: " . Song::type_to_mime($transcode_to) . "\r\n");
|
||||
fwrite($sock, "Accept-Ranges: none\r\n");
|
||||
|
||||
$genre = $channel->get_genre();
|
||||
// Send Shoutcast metadata on demand
|
||||
if ($options['metadata']) {
|
||||
fwrite($sock, "icy-notice1: " . AmpConfig::get('title') . "\r\n");
|
||||
fwrite($sock, "icy-name: " . $channel->name . "\r\n");
|
||||
if (!empty($genre)) {
|
||||
fwrite($sock, "icy-genre: " . $genre . "\r\n");
|
||||
}
|
||||
fwrite($sock, "icy-url: " . $channel->url . "\r\n");
|
||||
fwrite($sock, "icy-pub: " . ($channel->is_private) ? '0' : '1' . "\r\n");
|
||||
if ($channel->bitrate) {
|
||||
fwrite($sock, "icy-br: " . strval($channel->bitrate) . "\r\n");
|
||||
}
|
||||
fwrite($sock, "icy-metaint: " . strval($metadata_interval) . "\r\n");
|
||||
}
|
||||
// Send additional Icecast metadata
|
||||
fwrite($sock, "x-audiocast-server-url: " . $channel->url . "\r\n");
|
||||
fwrite($sock, "x-audiocast-name: " . $channel->name . "\r\n");
|
||||
fwrite($sock, "x-audiocast-description: " . $channel->description . "\r\n");
|
||||
fwrite($sock, "x-audiocast-url: " . $channel->url . "\r\n");
|
||||
if (!empty($genre)) {
|
||||
fwrite($sock, "x-audiocast-genre: " . $genre . "\r\n");
|
||||
}
|
||||
fwrite($sock, "x-audiocast-bitrate: " . strval($channel->bitrate) . "\r\n");
|
||||
fwrite($sock, "x-audiocast-public: " . (($channel->is_private) ? "0" : "1") . "\r\n");
|
||||
|
||||
fwrite($sock, "\r\n");
|
||||
|
||||
// Add to stream clients list
|
||||
$key = array_search($sock, $read_socks);
|
||||
$stream_clients[$key] = $options;
|
||||
break;
|
||||
|
||||
case '/':
|
||||
case '/status.xsl':
|
||||
// Stream request
|
||||
fwrite($sock, "HTTP/1.0 200 OK\r\n");
|
||||
fwrite($sock, "Cache-Control: no-store, no-cache, must-revalidate\r\n");
|
||||
fwrite($sock, "Content-Type: text/html\r\n");
|
||||
fwrite($sock, "\r\n");
|
||||
|
||||
// Create xsl structure
|
||||
|
||||
// Header
|
||||
$xsl = "";
|
||||
$xsl .= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" . "\n";
|
||||
$xsl .= "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" . "\n";
|
||||
$xsl .= "<html xmlns=\"http://www.w3.org/1999/xhtml\">" . "\n";
|
||||
$xsl .= "<head>" . "\n";
|
||||
$xsl .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />" . "\n";
|
||||
$xsl .= "<title>Icecast Streaming Media Server - Ampache</title>" . "\n";
|
||||
$xsl .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />" . "\n";
|
||||
$xsl .= "</head>" . "\n";
|
||||
$xsl .= "<body>" . "\n";
|
||||
$xsl .= "<div class=\"main\">" . "\n";
|
||||
|
||||
// Content
|
||||
$xsl .= "<div class=\"roundcont\">" . "\n";
|
||||
$xsl .= "<div class=\"roundtop\">" . "\n";
|
||||
$xsl .= "<img src=\"images/corner_topleft.jpg\" class=\"corner\" style=\"display: none\" alt=\"\" />" . "\n";
|
||||
$xsl .= "</div>" . "\n";
|
||||
$xsl .= "<div class=\"newscontent\">" . "\n";
|
||||
$xsl .= "<div class=\"streamheader\">" . "\n";
|
||||
$xsl .= "<table cellspacing=\"0\" cellpadding=\"0\">" . "\n";
|
||||
$xsl .= "<colgroup align=\"left\"></colgroup>" . "\n";
|
||||
$xsl .= "<colgroup align=\"right\" width=\"300\"></colgroup>" . "\n";
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td><h3>Mount Point /stream." . $channel->stream_type . "</h3></td>" . "\n";
|
||||
$xsl .= "<td align=\"right\">" . "\n";
|
||||
$xsl .= "<a href=\"stream.". $channel->stream_type .".m3u\">M3U</a>" . "\n";
|
||||
$xsl .= "</td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$xsl .= "</table>" . "\n";
|
||||
$xsl .= "</div>" . "\n";
|
||||
$xsl .= "<table border=\"0\" cellpadding=\"4\">" . "\n";
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td>Stream Title:</td>" . "\n";
|
||||
$xsl .= "<td class=\"streamdata\">" . $channel->name . "</td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td>Stream Description:</td>" . "\n";
|
||||
$xsl .= "<td class=\"streamdata\">" . $channel->description . "</td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td>Content Type:</td>" . "\n";
|
||||
$xsl .= "<td class=\"streamdata\">" . Song::type_to_mime($channel->stream_type) . "</td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td>Mount Start:</td>" . "\n";
|
||||
$xsl .= "<td class=\"streamdata\">" . date("c", $channel->start_date) . "</td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td>Bitrate:</td>" . "\n";
|
||||
$xsl .= "<td class=\"streamdata\">" . $channel->bitrate . "</td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td>Current Listeners:</td>" . "\n";
|
||||
$xsl .= "<td class=\"streamdata\">" . $channel->listeners . "</td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td>Peak Listeners:</td>" . "\n";
|
||||
$xsl .= "<td class=\"streamdata\">" . $channel->peak_listeners . "</td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$genre = $channel->get_genre();
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td>Stream Genre:</td>" . "\n";
|
||||
$xsl .= "<td class=\"streamdata\">" . $genre . "</td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td>Stream URL:</td>" . "\n";
|
||||
$xsl .= "<td class=\"streamdata\"><a href=\"" . $channel->url . "\" target=\"_blank\">" . $channel->url . "</a></td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$currentsong = "";
|
||||
if ($channel->media) {
|
||||
$currentsong = $channel->media->f_artist . " - " . $channel->media->f_title;
|
||||
}
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td>Current Song:</td>" . "\n";
|
||||
$xsl .= "<td class=\"streamdata\">" . $currentsong . "</td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$xsl .= "</table>" . "\n";
|
||||
$xsl .= "</div>" . "\n";
|
||||
$xsl .= "<div class=\"roundbottom\">" . "\n";
|
||||
$xsl .= "<img src=\"images/corner_bottomleft.jpg\" class=\"corner\" style=\"display: none\" alt=\"\" />" . "\n";
|
||||
$xsl .= "</div>" . "\n";
|
||||
$xsl .= "</div>" . "\n";
|
||||
$xsl .= "<br /><br />" . "\n";
|
||||
|
||||
// Footer
|
||||
$xsl .= "<div class=\"poster\">" . "\n";
|
||||
$xsl .= "Support Icecast development at <a target=\"_blank\" href=\"http://www.icecast.org\">www.icecast.org</a>" . "\n";
|
||||
$xsl .= "</div>" . "\n";
|
||||
$xsl .= "</div>" . "\n";
|
||||
$xsl .= "</body>" . "\n";
|
||||
$xsl .= "</html>" . "\n";
|
||||
|
||||
fwrite($sock, $xsl);
|
||||
|
||||
fclose($sock);
|
||||
unset($client_socks[array_search($sock, $client_socks)]);
|
||||
break;
|
||||
|
||||
case '/style.css':
|
||||
case '/favicon.ico':
|
||||
case '/images/corner_bottomleft.jpg':
|
||||
case '/images/corner_bottomright.jpg':
|
||||
case '/images/corner_topleft.jpg':
|
||||
case '/images/corner_topright.jpg':
|
||||
case '/images/icecast.png':
|
||||
case '/images/key.png':
|
||||
case '/images/tunein.png':
|
||||
// Get read file data
|
||||
$fpath = AmpConfig::get('prefix') . '/channel' . $cmd['1'];
|
||||
$pinfo = pathinfo($fpath);
|
||||
|
||||
$content_type = 'text/html';
|
||||
switch ($pinfo['extension']) {
|
||||
case 'css':
|
||||
$content_type = "text/css";
|
||||
break;
|
||||
case 'jpg':
|
||||
$content_type = "image/jpeg";
|
||||
break;
|
||||
case 'png':
|
||||
$content_type = "image/png";
|
||||
break;
|
||||
case 'ico':
|
||||
$content_type = "image/vnd.microsoft.icon";
|
||||
break;
|
||||
}
|
||||
fwrite($sock, "HTTP/1.0 200 OK\r\n");
|
||||
fwrite($sock, "Content-Type: " . $content_type . "\r\n");
|
||||
$fdata = file_get_contents($fpath);
|
||||
fwrite($sock, "Content-Length: " . strlen($fdata) . "\r\n");
|
||||
fwrite($sock, "\r\n");
|
||||
fwrite($sock, $fdata);
|
||||
fclose($sock);
|
||||
unset($client_socks[array_search($sock, $client_socks)]);
|
||||
break;
|
||||
case '/stream.' . $channel->stream_type . '.m3u':
|
||||
fwrite($sock, "HTTP/1.0 200 OK\r\n");
|
||||
fwrite($sock, "Cache-control: public\r\n");
|
||||
fwrite($sock, "Content-Disposition: filename=stream." . $channel->stream_type . ".m3u\r\n");
|
||||
fwrite($sock, "Content-Type: audio/x-mpegurl\r\n");
|
||||
fwrite($sock, "\r\n");
|
||||
|
||||
fwrite($sock, $channel->get_stream_url() . "\n");
|
||||
|
||||
fclose($sock);
|
||||
unset($client_socks[array_search($sock, $client_socks)]);
|
||||
break;
|
||||
default:
|
||||
debug_event('channel', 'Unknown request. Closing connection.', '3');
|
||||
fclose($sock);
|
||||
unset($client_socks[array_search($sock, $client_socks)]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Handle data parse
|
||||
http_serve($channel, $client_socks, $stream_clients, $read_socks, $sock);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($channel->bitrate) {
|
||||
|
||||
$time_offset = microtime(true) - $last_stream;
|
||||
//$mtime = ($last_stream > 0 && $time_offset < 1000000) ? $time_offset : 1;
|
||||
$mtime = 1;
|
||||
if ($last_stream > 0 && $time_offset < 1) {
|
||||
usleep(1000000 - ($time_offset * 1000000));
|
||||
} elseif ($last_stream > 0) {
|
||||
//$mtime = $time_offset;
|
||||
|
||||
//debug_event('channel', 'time_offset : '. $time_offset, '5');
|
||||
//debug_event('channel', 'last_stream: '.$last_stream, '5');
|
||||
|
||||
if ($time_offset < 1)
|
||||
usleep(1000000 - ($time_offset * 1000000)); // always at least 1 second between cycles
|
||||
|
||||
$last_stream = microtime(true);
|
||||
$mtime = ($time_offset > 1) ? $time_offset : 1;
|
||||
$nb_chunks = ceil(($mtime * ($channel->bitrate+1/100*$channel->bitrate) * 1000 / 8) / $channel->chunk_size); // channel->bitrate+1% ... leave some headroom for metadata / headers
|
||||
|
||||
// we only send full blocks, save remainder and apply when appropriate: allows more granular/arbitrary average bitrates
|
||||
if ($nb_chunks - ($mtime * ($channel->bitrate+1/100*$channel->bitrate) * 1000 / 8 / $channel->chunk_size) > 0)
|
||||
$nb_chunks_remainder += $nb_chunks - ($mtime * $channel->bitrate * 1000 / 8 / $channel->chunk_size);
|
||||
if ($nb_chunks >= 1 && $nb_chunks_remainder >= 1){
|
||||
$nb_chunks -= 1;
|
||||
$nb_chunks_remainder -= 1;
|
||||
//debug_event('channel', 'REMAINDER: '.$nb_chunks_remainder, '5');
|
||||
}
|
||||
$nb_chunks = ceil(($mtime * $channel->bitrate * 1000) / 4096);
|
||||
//debug_event('channel', 'mtime '.$mtime, '5');
|
||||
//debug_event('channel', 'nb_chunks: '.$nb_chunks, '5');
|
||||
|
||||
} else {
|
||||
$nb_chunks = 1;
|
||||
}
|
||||
|
||||
|
||||
// Get multiple chunks according to bitrate to return enough data per second (because sleep with socket select)
|
||||
for ($c = 0; $c < $nb_chunks; $c++) {
|
||||
|
||||
$chunk = $channel->get_chunk();
|
||||
$chunklen = strlen($chunk);
|
||||
$chunk_buffer .= $chunk;
|
||||
|
||||
//buffer maintenance
|
||||
while (strlen($chunk_buffer) > (15 * $nb_chunks * $channel->chunk_size) ){ // buffer 15 seconds
|
||||
|
||||
if (strtolower($channel->stream_type) == "ogg" && strtohex(substr($chunk_buffer, 0, 4)) == "4F676753") { //maintain ogg chunk alignment --- "4F676753" == "OggS"
|
||||
// read OggS segment length
|
||||
$hex = strtohex(substr($chunk_buffer, 0, 27));
|
||||
$ogg_nr_of_segments = hexdec(substr($hex, 26*2, 2));
|
||||
$hex .= strtohex(substr($chunk_buffer, 27, $ogg_nr_of_segments));
|
||||
$ogg_sum_segm_laces = 0;
|
||||
for($segm = 0; $segm < $ogg_nr_of_segments; $segm++){
|
||||
$ogg_sum_segm_laces += hexdec(substr($hex, 27*2 + $segm*2, 2));
|
||||
}
|
||||
//$naive = strpos(substr($chunk_buffer, 4), 'OggS') + 4; // naive search for next header
|
||||
//remove 1 whole OggS chunk
|
||||
$chunk_buffer = substr($chunk_buffer, 27 + $ogg_nr_of_segments + $ogg_sum_segm_laces);
|
||||
//debug_event('channel', '$new chunk buffer : '.substr($chunk_buffer,0,300) . ' $hex: '.strtohex(substr($chunk_buffer,0,600)) . ' $ogg_nr_of_segments: ' .$ogg_nr_of_segments . ' bytes cut off: '.(27 + $ogg_nr_of_segments + $ogg_sum_segm_laces) . ' naive: ' .$naive, '5');
|
||||
} elseif (strtolower($channel->stream_type) == "ogg") {
|
||||
debug_event('channel', 'Ogg alignament broken! Trying repair...', '5');
|
||||
$manual_search = strpos($chunk_buffer, 'OggS');
|
||||
$chunk_buffer = substr($chunk_buffer, $manual_search);
|
||||
} else { // no chunk alignment required
|
||||
$chunk_buffer = substr($chunk_buffer, $chunklen);
|
||||
}
|
||||
//debug_event('channel', 'remvd chunk from buffer ', '5');
|
||||
}
|
||||
|
||||
if ($chunklen > 0) {
|
||||
foreach($stream_clients as $key => $client)
|
||||
{
|
||||
$sock = $client['socket'];
|
||||
$clchunk = $chunk;
|
||||
|
||||
if(!is_resource($sock)) {
|
||||
client_disconnect($channel, $client_socks, $stream_clients, $sock);
|
||||
continue;
|
||||
}
|
||||
|
||||
$clchunk = $chunk;
|
||||
|
||||
if ($client['isnew'] == 1){
|
||||
$client['isnew'] = 0;
|
||||
//fwrite($sock, $channel->header_chunk);
|
||||
//debug_event('channel', 'IS NEW' . $channel->header_chunk, '5');
|
||||
$clchunk_buffer = $channel->header_chunk . $chunk_buffer;
|
||||
if ($client['metadata']){ //stub
|
||||
//if (strtolower($channel->stream_type) == "ogg")
|
||||
while(strlen($clchunk_buffer) > $metadata_interval){
|
||||
fwrite($sock, substr($clchunk_buffer, 0, $metadata_interval) . chr(0x00));
|
||||
$clchunk_buffer = substr($clchunk_buffer, $metadata_interval);
|
||||
}
|
||||
fwrite($sock, $clchunk_buffer);
|
||||
$client['metadata_lastsent'] = 0;
|
||||
$client['length'] += strlen($clchunk_buffer);
|
||||
} else {
|
||||
//fwrite($sock, $channel->header_chunk);
|
||||
$buffer_bytes_written = fwrite($sock, $clchunk_buffer);
|
||||
while ($buffer_bytes_written != strlen($clchunk_buffer)){
|
||||
debug_event('channel', 'I HERPED WHEN I SHOULD HAVE DERPED!', '5');
|
||||
//debug_event('channel', 'chunk_buffer bytes written:' .$buffer_bytes_written .'strlen $chunk_buffer: '.strlen($chunk_buffer), '5');
|
||||
$clchunk_buffer = substr($clchunk_buffer, $buffer_bytes_written);
|
||||
$buffer_bytes_written = fwrite($sock, $clchunk_buffer);
|
||||
}
|
||||
}
|
||||
$stream_clients[$key] = $client;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if we need to insert metadata information
|
||||
if ($client['metadata']) {
|
||||
$chkmdlen = ($client['length'] + $chunklen) - $client['metadata_lastsent'];
|
||||
|
@ -437,24 +270,23 @@ while(true)
|
|||
$clchunk = substr($chunk, $subpos);
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen($clchunk) > 0) {
|
||||
fwrite($sock, $clchunk);
|
||||
$client['length'] += strlen($clchunk);
|
||||
}
|
||||
|
||||
$stream_clients[$key] = $client;
|
||||
//debug_event('channel', 'Client stream current length: ' . $client['length'], '5');
|
||||
}
|
||||
} else {
|
||||
$channel->update_listeners(0);
|
||||
debug_event('channel', 'No more data, stream ended.', 5);
|
||||
die('No more data, stream ended.');
|
||||
}
|
||||
|
||||
$last_stream = microtime(true);
|
||||
}
|
||||
}
|
||||
|
||||
ob_end_flush();
|
||||
ob_end_flush();
|
||||
echo "\n";
|
||||
|
||||
function client_disconnect($channel, &$client_socks, &$stream_clients, $sock)
|
||||
|
@ -474,7 +306,7 @@ function usage()
|
|||
echo T_("- Channel Listening -");
|
||||
echo "\n";
|
||||
echo T_("Usage: channel_run.inc [-c {CHANNEL ID}|-p {PORT}|-v]");
|
||||
echo "\n\t";
|
||||
echo "\n\t";
|
||||
echo "\n-c {CHANNEL ID}\t";
|
||||
echo T_('Channel id to start');
|
||||
echo "\n-p {PORT}\t";
|
||||
|
@ -486,4 +318,261 @@ function usage()
|
|||
echo "\n";
|
||||
}
|
||||
|
||||
function http_serve($channel, &$client_socks, &$stream_clients, &$read_socks, $sock)
|
||||
{
|
||||
$data = fread($sock, 1024);
|
||||
if(!$data)
|
||||
{
|
||||
client_disconnect($channel, $client_socks, $stream_clients, $sock);
|
||||
return;
|
||||
}
|
||||
|
||||
$headers = explode("\n", $data);
|
||||
|
||||
if (count($headers) > 0) {
|
||||
$cmd = explode(" ", $headers[0]);
|
||||
if ($cmd['0'] == 'GET') {
|
||||
switch ($cmd['1']) {
|
||||
case '/stream.' . $channel->stream_type:
|
||||
$options = array(
|
||||
'socket' => $sock,
|
||||
'length' => 0,
|
||||
'isnew' => 1
|
||||
);
|
||||
|
||||
//debug_event('channel', 'HTTP HEADERS: '.$data,'5');
|
||||
for ($i = 1; $i < count($headers); $i++) {
|
||||
$headerpart = explode(":", $headers[$i], 2);
|
||||
$header = strtolower(trim($headerpart[0]));
|
||||
$value = trim($headerpart[1]);
|
||||
switch ($header) {
|
||||
case 'icy-metadata':
|
||||
$options['metadata'] = ($value == '1');
|
||||
$options['metadata_lastsent'] = 0;
|
||||
$options['metadata_lastsong'] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Stream request
|
||||
if ($options['metadata']) {
|
||||
//$http = "ICY 200 OK\r\n");
|
||||
$http = "HTTP/1.0 200 OK\r\n";
|
||||
} else {
|
||||
$http = "HTTP/1.1 200 OK\r\n";
|
||||
$http .= "Cache-Control: no-store, no-cache, must-revalidate\r\n";
|
||||
}
|
||||
$http .= "Content-Type: " . Song::type_to_mime($channel->stream_type) . "\r\n";
|
||||
$http .= "Accept-Ranges: none\r\n";
|
||||
|
||||
$genre = $channel->get_genre();
|
||||
// Send Shoutcast metadata on demand
|
||||
//if ($options['metadata']) {
|
||||
$http .= "icy-notice1: " . AmpConfig::get('site_title') . "\r\n";
|
||||
$http .= "icy-name: " . $channel->name . "\r\n";
|
||||
if (!empty($genre)) {
|
||||
$http .= "icy-genre: " . $genre . "\r\n";
|
||||
}
|
||||
$http .= "icy-url: " . $channel->url . "\r\n";
|
||||
$http .= "icy-pub: " . (($channel->is_private) ? "0" : "1") . "\r\n";
|
||||
if ($channel->bitrate) {
|
||||
$http .= "icy-br: " . strval($channel->bitrate) . "\r\n";
|
||||
}
|
||||
global $metadata_interval;
|
||||
$http .= "icy-metaint: " . strval($metadata_interval) . "\r\n";
|
||||
//}
|
||||
// Send additional Icecast metadata
|
||||
$http .= "x-audiocast-server-url: " . $channel->url . "\r\n";
|
||||
$http .= "x-audiocast-name: " . $channel->name . "\r\n";
|
||||
$http .= "x-audiocast-description: " . $channel->description . "\r\n";
|
||||
$http .= "x-audiocast-url: " . $channel->url . "\r\n";
|
||||
if (!empty($genre)) {
|
||||
$http .= "x-audiocast-genre: " . $genre . "\r\n";
|
||||
}
|
||||
$http .= "x-audiocast-bitrate: " . strval($channel->bitrate) . "\r\n";
|
||||
$http .= "x-audiocast-public: " . (($channel->is_private) ? "0" : "1") . "\r\n";
|
||||
|
||||
$http .= "\r\n";
|
||||
|
||||
fwrite($sock, $http);
|
||||
|
||||
// Add to stream clients list
|
||||
$key = array_search($sock, $read_socks);
|
||||
$stream_clients[$key] = $options;
|
||||
break;
|
||||
|
||||
case '/':
|
||||
case '/status.xsl':
|
||||
// Stream request
|
||||
fwrite($sock, "HTTP/1.0 200 OK\r\n");
|
||||
fwrite($sock, "Cache-Control: no-store, no-cache, must-revalidate\r\n");
|
||||
fwrite($sock, "Content-Type: text/html\r\n");
|
||||
fwrite($sock, "\r\n");
|
||||
|
||||
// Create xsl structure
|
||||
|
||||
// Header
|
||||
$xsl = "";
|
||||
$xsl .= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" . "\n";
|
||||
$xsl .= "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" . "\n";
|
||||
$xsl .= "<html xmlns=\"http://www.w3.org/1999/xhtml\">" . "\n";
|
||||
$xsl .= "<head>" . "\n";
|
||||
$xsl .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />" . "\n";
|
||||
$xsl .= "<title>Icecast Streaming Media Server - Ampache</title>" . "\n";
|
||||
$xsl .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />" . "\n";
|
||||
$xsl .= "</head>" . "\n";
|
||||
$xsl .= "<body>" . "\n";
|
||||
$xsl .= "<div class=\"main\">" . "\n";
|
||||
|
||||
// Content
|
||||
$xsl .= "<div class=\"roundcont\">" . "\n";
|
||||
$xsl .= "<div class=\"roundtop\">" . "\n";
|
||||
$xsl .= "<img src=\"images/corner_topleft.jpg\" class=\"corner\" style=\"display: none\" alt=\"\" />" . "\n";
|
||||
$xsl .= "</div>" . "\n";
|
||||
$xsl .= "<div class=\"newscontent\">" . "\n";
|
||||
$xsl .= "<div class=\"streamheader\">" . "\n";
|
||||
$xsl .= "<table cellspacing=\"0\" cellpadding=\"0\">" . "\n";
|
||||
$xsl .= "<colgroup align=\"left\"></colgroup>" . "\n";
|
||||
$xsl .= "<colgroup align=\"right\" width=\"300\"></colgroup>" . "\n";
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td><h3>Mount Point /stream." . $channel->stream_type . "</h3></td>" . "\n";
|
||||
$xsl .= "<td align=\"right\">" . "\n";
|
||||
$xsl .= "<a href=\"stream.". $channel->stream_type .".m3u\">M3U</a>" . "\n";
|
||||
$xsl .= "</td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$xsl .= "</table>" . "\n";
|
||||
$xsl .= "</div>" . "\n";
|
||||
$xsl .= "<table border=\"0\" cellpadding=\"4\">" . "\n";
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td>Stream Title:</td>" . "\n";
|
||||
$xsl .= "<td class=\"streamdata\">" . $channel->name . "</td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td>Stream Description:</td>" . "\n";
|
||||
$xsl .= "<td class=\"streamdata\">" . $channel->description . "</td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td>Content Type:</td>" . "\n";
|
||||
$xsl .= "<td class=\"streamdata\">" . Song::type_to_mime($channel->stream_type) . "</td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td>Mount Start:</td>" . "\n";
|
||||
$xsl .= "<td class=\"streamdata\">" . date("c", $channel->start_date) . "</td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td>Bitrate:</td>" . "\n";
|
||||
$xsl .= "<td class=\"streamdata\">" . $channel->bitrate . "</td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td>Current Listeners:</td>" . "\n";
|
||||
$xsl .= "<td class=\"streamdata\">" . $channel->listeners . "</td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td>Peak Listeners:</td>" . "\n";
|
||||
$xsl .= "<td class=\"streamdata\">" . $channel->peak_listeners . "</td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$genre = $channel->get_genre();
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td>Stream Genre:</td>" . "\n";
|
||||
$xsl .= "<td class=\"streamdata\">" . $genre . "</td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td>Stream URL:</td>" . "\n";
|
||||
$xsl .= "<td class=\"streamdata\"><a href=\"" . $channel->url . "\" target=\"_blank\">" . $channel->url . "</a></td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$currentsong = "";
|
||||
if ($channel->media) {
|
||||
$currentsong = $channel->media->f_artist . " - " . $channel->media->f_title;
|
||||
}
|
||||
$xsl .= "<tr>" . "\n";
|
||||
$xsl .= "<td>Current Song:</td>" . "\n";
|
||||
$xsl .= "<td class=\"streamdata\">" . $currentsong . "</td>" . "\n";
|
||||
$xsl .= "</tr>" . "\n";
|
||||
$xsl .= "</table>" . "\n";
|
||||
$xsl .= "</div>" . "\n";
|
||||
$xsl .= "<div class=\"roundbottom\">" . "\n";
|
||||
$xsl .= "<img src=\"images/corner_bottomleft.jpg\" class=\"corner\" style=\"display: none\" alt=\"\" />" . "\n";
|
||||
$xsl .= "</div>" . "\n";
|
||||
$xsl .= "</div>" . "\n";
|
||||
$xsl .= "<br /><br />" . "\n";
|
||||
|
||||
// Footer
|
||||
$xsl .= "<div class=\"poster\">" . "\n";
|
||||
$xsl .= "Support Ampache at <a target=\"_blank\" href=\"http://www.ampache.org\">www.ampache.org</a>" . "\n";
|
||||
$xsl .= "</div>" . "\n";
|
||||
$xsl .= "</div>" . "\n";
|
||||
$xsl .= "</body>" . "\n";
|
||||
$xsl .= "</html>" . "\n";
|
||||
|
||||
fwrite($sock, $xsl);
|
||||
|
||||
fclose($sock);
|
||||
unset($client_socks[array_search($sock, $client_socks)]);
|
||||
break;
|
||||
|
||||
case '/style.css':
|
||||
case '/favicon.ico':
|
||||
case '/images/corner_bottomleft.jpg':
|
||||
case '/images/corner_bottomright.jpg':
|
||||
case '/images/corner_topleft.jpg':
|
||||
case '/images/corner_topright.jpg':
|
||||
case '/images/icecast.png':
|
||||
case '/images/key.png':
|
||||
case '/images/tunein.png':
|
||||
// Get read file data
|
||||
$fpath = AmpConfig::get('prefix') . '/channel' . $cmd['1'];
|
||||
$pinfo = pathinfo($fpath);
|
||||
|
||||
$content_type = 'text/html';
|
||||
switch ($pinfo['extension']) {
|
||||
case 'css':
|
||||
$content_type = "text/css";
|
||||
break;
|
||||
case 'jpg':
|
||||
$content_type = "image/jpeg";
|
||||
break;
|
||||
case 'png':
|
||||
$content_type = "image/png";
|
||||
break;
|
||||
case 'ico':
|
||||
$content_type = "image/vnd.microsoft.icon";
|
||||
break;
|
||||
}
|
||||
fwrite($sock, "HTTP/1.0 200 OK\r\n");
|
||||
fwrite($sock, "Content-Type: " . $content_type . "\r\n");
|
||||
$fdata = file_get_contents($fpath);
|
||||
fwrite($sock, "Content-Length: " . strlen($fdata) . "\r\n");
|
||||
fwrite($sock, "\r\n");
|
||||
fwrite($sock, $fdata);
|
||||
fclose($sock);
|
||||
unset($client_socks[array_search($sock, $client_socks)]);
|
||||
break;
|
||||
case '/stream.' . $channel->stream_type . '.m3u':
|
||||
fwrite($sock, "HTTP/1.0 200 OK\r\n");
|
||||
fwrite($sock, "Cache-control: public\r\n");
|
||||
fwrite($sock, "Content-Disposition: filename=stream." . $channel->stream_type . ".m3u\r\n");
|
||||
fwrite($sock, "Content-Type: audio/x-mpegurl\r\n");
|
||||
fwrite($sock, "\r\n");
|
||||
|
||||
fwrite($sock, $channel->get_stream_url() . "\n");
|
||||
|
||||
fclose($sock);
|
||||
unset($client_socks[array_search($sock, $client_socks)]);
|
||||
break;
|
||||
default:
|
||||
debug_event('channel', 'Unknown request. Closing connection.', '3');
|
||||
fclose($sock);
|
||||
unset($client_socks[array_search($sock, $client_socks)]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function strtohex($x) {
|
||||
$s='';
|
||||
foreach(str_split($x) as $c) $s.=sprintf("%02X",ord($c));
|
||||
return($s);
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -75,7 +75,7 @@ while ($row = Dba::fetch_assoc($db_results)) {
|
|||
|
||||
} // end of the catalogs
|
||||
|
||||
echo T_('Finished checking filenames for valid chacters');
|
||||
echo T_('Finished checking file names for valid characters');
|
||||
echo "\n";
|
||||
|
||||
/**************************************************
|
||||
|
@ -191,13 +191,13 @@ function charset_rename_file($full_file,$translated_filename) {
|
|||
$results = copy($full_file,$translated_filename);
|
||||
|
||||
if (!$results) {
|
||||
echo T_('Error: Copy Failed, not deleteing old file');
|
||||
echo T_('Error: Copy Failed, not deleting old file');
|
||||
echo "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
$old_sum = filesize($full_file);
|
||||
$new_sum = filesize($translated_filename);
|
||||
$old_sum = Core::get_filesize($full_file);
|
||||
$new_sum = Core::get_filesize($translated_filename);
|
||||
|
||||
if ($old_sum != $new_sum OR !$new_sum) {
|
||||
printf (T_('Error: Size Inconsistency, not deleting %s'), $full_file);
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Deny from all
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -53,7 +53,7 @@ $catalog = Catalog::create_from_id($results['id']);
|
|||
$dir_pattern = $catalog->sort_pattern;
|
||||
$file_pattern = $catalog->rename_pattern;
|
||||
|
||||
$info = new vainfo($filename, '', '', '', $dir_pattern, $file_pattern);
|
||||
$info = new vainfo($filename, array('music'), '', '', '', $dir_pattern, $file_pattern);
|
||||
if(isset($dir_pattern) || isset($file_pattern)) {
|
||||
printf(T_('Using: %s AND %s for file pattern matching'), $dir_pattern, $file_pattern);
|
||||
print "\n";
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -65,7 +65,6 @@ while ($r = Dba::fetch_row($db_results)) {
|
|||
foreach ($songs as $song) {
|
||||
/* Find this poor song a home */
|
||||
$song->format();
|
||||
$song->format_pattern();
|
||||
$directory = sort_find_home($song,$catalog->sort_pattern,$catalog->path);
|
||||
$filename = $song->f_file;
|
||||
$fullpath = $directory . "/" . $filename;
|
||||
|
@ -268,12 +267,12 @@ function sort_move_file($song,$fullname) {
|
|||
|
||||
/* Look for the folder art and copy that as well */
|
||||
if (!AmpConfig::get('album_art_preferred_filename') OR strstr(AmpConfig::get('album_art_preferred_filename'),"%")) {
|
||||
$folder_art = $directory . '/folder.jpg';
|
||||
$old_art = $old_dir . '/folder.jpg';
|
||||
$folder_art = $directory . DIRECTORY_SEPARATOR . 'folder.jpg';
|
||||
$old_art = $old_dir . DIRECTORY_SEPARATOR . 'folder.jpg';
|
||||
}
|
||||
else {
|
||||
$folder_art = $directory . "/" . sort_clean_name(AmpConfig::get('album_art_preferred_filename'));
|
||||
$old_art = $old_dir . "/" . sort_clean_name(AmpConfig::get('album_art_preferred_filename'));
|
||||
$folder_art = $directory . DIRECTORY_SEPARATOR . sort_clean_name(AmpConfig::get('album_art_preferred_filename'));
|
||||
$old_art = $old_dir . DIRECTORY_SEPARATOR . sort_clean_name(AmpConfig::get('album_art_preferred_filename'));
|
||||
}
|
||||
|
||||
debug_event('copy_art','Copied ' . $old_art . ' to ' . $folder_art,'5');
|
||||
|
@ -282,8 +281,8 @@ function sort_move_file($song,$fullname) {
|
|||
if (!$results) { printf (T_('Error: Unable to copy file to %s'), $fullname); echo "\n"; return false; }
|
||||
|
||||
/* Check the filesize */
|
||||
$new_sum = filesize($fullname);
|
||||
$old_sum = filesize($song->file);
|
||||
$new_sum = Core::get_filesize($fullname);
|
||||
$old_sum = Core::get_filesize($song->file);
|
||||
|
||||
if ($new_sum != $old_sum OR !$new_sum) {
|
||||
printf (T_('Error: Size Inconsistency, not deleting %s'), $song->file);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -35,7 +35,7 @@ else {
|
|||
|
||||
// Make sure the output dir is valid and writeable
|
||||
if (!is_writeable($dirname)) {
|
||||
printf (T_('Error: Directory %s not writeable'), $dirname);
|
||||
printf (T_('Error: Directory %s is not writable'), $dirname);
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -22,12 +22,16 @@
|
|||
|
||||
require_once 'lib/init.php';
|
||||
|
||||
if (!AmpConfig::get('broadcast')) {
|
||||
UI::access_denied();
|
||||
exit;
|
||||
}
|
||||
|
||||
UI::show_header();
|
||||
|
||||
/* Switch on the action passed in */
|
||||
switch ($_REQUEST['action']) {
|
||||
case 'show_delete':
|
||||
UI::show_header();
|
||||
$id = $_REQUEST['id'];
|
||||
|
||||
$next_url = AmpConfig::get('web_path') . '/broadcast.php?action=delete&id=' . scrub_out($id);
|
||||
|
@ -40,7 +44,6 @@ switch ($_REQUEST['action']) {
|
|||
exit;
|
||||
}
|
||||
|
||||
UI::show_header();
|
||||
$id = $_REQUEST['id'];
|
||||
$broadcast = new Broadcast($id);
|
||||
if ($broadcast->delete()) {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -49,6 +49,14 @@ switch ($_REQUEST['action']) {
|
|||
case 'song':
|
||||
case 'channel':
|
||||
case 'broadcast':
|
||||
case 'tvshow':
|
||||
case 'tvshow_season':
|
||||
case 'tvshow_episode':
|
||||
case 'movie':
|
||||
case 'clip':
|
||||
case 'personal_video':
|
||||
case 'label':
|
||||
case 'pvmsg':
|
||||
$browse->set_type($_REQUEST['action']);
|
||||
$browse->set_simple_browse(true);
|
||||
break;
|
||||
|
@ -56,6 +64,9 @@ switch ($_REQUEST['action']) {
|
|||
|
||||
UI::show_header();
|
||||
|
||||
// Browser is able to save page on current session. Only applied to main menus.
|
||||
$browse->set_update_session(true);
|
||||
|
||||
switch ($_REQUEST['action']) {
|
||||
case 'file':
|
||||
break;
|
||||
|
@ -65,20 +76,22 @@ switch ($_REQUEST['action']) {
|
|||
$browse->set_filter('catalog_enabled', '1');
|
||||
}
|
||||
$browse->set_sort('name','ASC');
|
||||
$browse->update_browse_from_session(); // Update current index depending on what is in session.
|
||||
$browse->show_objects();
|
||||
break;
|
||||
case 'tag':
|
||||
//FIXME: This whole thing is ugly, even though it works.
|
||||
$browse->set_sort('count','ASC');
|
||||
// This one's a doozy
|
||||
$browse_type = isset($_REQUEST['type']) ? $_REQUEST['type'] : 'song';
|
||||
$browse->set_simple_browse(false);
|
||||
$browse->save_objects(Tag::get_tags(/*AmpConfig::get('offset_limit')*/)); // Should add a pager?
|
||||
$browse->save_objects(Tag::get_tags($browse_type, 0, 'name')); // Should add a pager?
|
||||
$object_ids = $browse->get_saved();
|
||||
$keys = array_keys($object_ids);
|
||||
Tag::build_cache($keys);
|
||||
UI::show_box_top(T_('Tag Cloud'), 'box box_tag_cloud');
|
||||
$browse2 = new Browse();
|
||||
$browse2->set_type('song');
|
||||
$browse2->set_type($browse_type);
|
||||
$browse2->store();
|
||||
require_once AmpConfig::get('prefix') . '/templates/show_tagcloud.inc.php';
|
||||
UI::show_box_bottom();
|
||||
|
@ -91,6 +104,7 @@ switch ($_REQUEST['action']) {
|
|||
$browse->set_filter('catalog_enabled', '1');
|
||||
}
|
||||
$browse->set_sort('name','ASC');
|
||||
$browse->update_browse_from_session();
|
||||
$browse->show_objects();
|
||||
break;
|
||||
case 'song':
|
||||
|
@ -99,6 +113,7 @@ switch ($_REQUEST['action']) {
|
|||
$browse->set_filter('catalog_enabled', '1');
|
||||
}
|
||||
$browse->set_sort('title','ASC');
|
||||
$browse->update_browse_from_session();
|
||||
$browse->show_objects();
|
||||
break;
|
||||
case 'live_stream':
|
||||
|
@ -106,6 +121,7 @@ switch ($_REQUEST['action']) {
|
|||
$browse->set_filter('catalog_enabled', '1');
|
||||
}
|
||||
$browse->set_sort('name','ASC');
|
||||
$browse->update_browse_from_session();
|
||||
$browse->show_objects();
|
||||
break;
|
||||
case 'catalog':
|
||||
|
@ -114,19 +130,23 @@ switch ($_REQUEST['action']) {
|
|||
case 'playlist':
|
||||
$browse->set_sort('type','ASC');
|
||||
$browse->set_filter('playlist_type','1');
|
||||
$browse->update_browse_from_session();
|
||||
$browse->show_objects();
|
||||
break;
|
||||
case 'smartplaylist':
|
||||
$browse->set_sort('type', 'ASC');
|
||||
$browse->set_filter('playlist_type','1');
|
||||
$browse->update_browse_from_session();
|
||||
$browse->show_objects();
|
||||
break;
|
||||
case 'channel':
|
||||
$browse->set_sort('id', 'ASC');
|
||||
$browse->update_browse_from_session();
|
||||
$browse->show_objects();
|
||||
break;
|
||||
case 'broadcast':
|
||||
$browse->set_sort('id', 'ASC');
|
||||
$browse->update_browse_from_session();
|
||||
$browse->show_objects();
|
||||
break;
|
||||
case 'video':
|
||||
|
@ -134,8 +154,54 @@ switch ($_REQUEST['action']) {
|
|||
$browse->set_filter('catalog_enabled', '1');
|
||||
}
|
||||
$browse->set_sort('title','ASC');
|
||||
$browse->update_browse_from_session();
|
||||
$browse->show_objects();
|
||||
break;
|
||||
case 'tvshow':
|
||||
if (AmpConfig::get('catalog_disable')) {
|
||||
$browse->set_filter('catalog_enabled', '1');
|
||||
}
|
||||
$browse->set_sort('name','ASC');
|
||||
$browse->update_browse_from_session();
|
||||
$browse->show_objects();
|
||||
break;
|
||||
case 'tvshow_season':
|
||||
if (AmpConfig::get('catalog_disable')) {
|
||||
$browse->set_filter('catalog_enabled', '1');
|
||||
}
|
||||
$browse->set_sort('season_number','ASC');
|
||||
$browse->update_browse_from_session();
|
||||
$browse->show_objects();
|
||||
break;
|
||||
case 'tvshow_episode':
|
||||
case 'movie':
|
||||
case 'clip':
|
||||
case 'personal_video':
|
||||
if (AmpConfig::get('catalog_disable')) {
|
||||
$browse->set_filter('catalog_enabled', '1');
|
||||
}
|
||||
$browse->update_browse_from_session();
|
||||
$browse->show_objects();
|
||||
break;
|
||||
case 'label':
|
||||
if (AmpConfig::get('catalog_disable')) {
|
||||
$browse->set_filter('catalog_enabled', '1');
|
||||
}
|
||||
$browse->set_sort('name','ASC');
|
||||
$browse->update_browse_from_session();
|
||||
$browse->show_objects();
|
||||
break;
|
||||
case 'pvmsg':
|
||||
$browse->set_sort('creation_date','DESC');
|
||||
$folder = $_REQUEST['folder'];
|
||||
if ($folder === "sent") {
|
||||
$browse->set_filter('user', $GLOBALS['user']->id);
|
||||
} else {
|
||||
$browse->set_filter('to_user', $GLOBALS['user']->id);
|
||||
}
|
||||
$browse->update_browse_from_session();
|
||||
$browse->show_objects();
|
||||
break;
|
||||
default:
|
||||
|
||||
break;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -22,13 +22,16 @@
|
|||
|
||||
require_once 'lib/init.php';
|
||||
|
||||
if (!AmpConfig::get('channel')) {
|
||||
UI::access_denied();
|
||||
exit;
|
||||
}
|
||||
|
||||
UI::show_header();
|
||||
|
||||
/* Switch on the action passed in */
|
||||
switch ($_REQUEST['action']) {
|
||||
case 'show_create':
|
||||
UI::show_header();
|
||||
|
||||
$type = Channel::format_type($_REQUEST['type']);
|
||||
if (!empty($type) && !empty($_REQUEST['id'])) {
|
||||
$object = new $type($_REQUEST['id']);
|
||||
|
@ -50,7 +53,6 @@ switch ($_REQUEST['action']) {
|
|||
exit;
|
||||
}
|
||||
|
||||
UI::show_header();
|
||||
$created = Channel::create($_REQUEST['name'], $_REQUEST['description'], $_REQUEST['url'], $_REQUEST['type'], $_REQUEST['id'], $_REQUEST['interface'], $_REQUEST['port'], $_REQUEST['admin_password'], $_REQUEST['private'] ?: 0, $_REQUEST['max_listeners'], $_REQUEST['random'] ?: 0, $_REQUEST['loop'] ?: 0, $_REQUEST['stream_type'], $_REQUEST['bitrate']);
|
||||
|
||||
if (!$created) {
|
||||
|
@ -62,7 +64,6 @@ switch ($_REQUEST['action']) {
|
|||
UI::show_footer();
|
||||
exit;
|
||||
case 'show_delete':
|
||||
UI::show_header();
|
||||
$id = $_REQUEST['id'];
|
||||
|
||||
$next_url = AmpConfig::get('web_path') . '/channel.php?action=delete&id=' . scrub_out($id);
|
||||
|
@ -75,7 +76,6 @@ switch ($_REQUEST['action']) {
|
|||
exit;
|
||||
}
|
||||
|
||||
UI::show_header();
|
||||
$id = $_REQUEST['id'];
|
||||
$channel = new Channel($id);
|
||||
if ($channel->delete()) {
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-s
|
||||
RewriteRule ^([0-9]+)/(.*)$ index.php?channel=$1&target=$2 [PT,L,QSA]
|
||||
RewriteRule ^([0-9]+)/(.*)$ /channel/index.php?channel=$1&target=$2 [PT,L,QSA]
|
||||
</IfModule>
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
|
|
@ -76,10 +76,6 @@ html, body {
|
|||
margin-bottom: 10px;
|
||||
background: url(images/icecast.png) no-repeat left center;
|
||||
}
|
||||
.main iframe {
|
||||
width: 100%;
|
||||
border: 0;
|
||||
}
|
||||
.news {
|
||||
font-family: Verdana, sans-serif;
|
||||
text-decoration: none;
|
||||
|
|
1
sources/config/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
ampache.cfg.php
|
|
@ -1,2 +1,10 @@
|
|||
Order deny,allow
|
||||
Deny from all
|
||||
# Apache 2.4
|
||||
<IfModule mod_authz_core.c>
|
||||
Require all denied
|
||||
</IfModule>
|
||||
|
||||
# Apache 2.2
|
||||
<IfModule mod_access.c>
|
||||
Order deny,allow
|
||||
Deny from all
|
||||
</IfModule>
|
|
@ -4,35 +4,41 @@
|
|||
;###################
|
||||
|
||||
; This value is used to detect quickly
|
||||
; if this config file is up to date
|
||||
; if this config file is up to date
|
||||
; this is compared against a value hard-coded
|
||||
; into the init script
|
||||
config_version = 16
|
||||
config_version = 29
|
||||
|
||||
;###################
|
||||
; Path Vars #
|
||||
;###################
|
||||
|
||||
; The http host of your server.
|
||||
; The public http host of your server.
|
||||
; If not set, retrieved automatically from client request.
|
||||
; This setting is required for WebSocket server
|
||||
; DEFAULT: ""
|
||||
;http_host = "localhost"
|
||||
|
||||
; The path to your ampache install
|
||||
; Do not put a trailing / on this path
|
||||
; The public path to your ampache install
|
||||
; Do not put a trailing / on this path
|
||||
; For example if your site is located at http://localhost
|
||||
; than you do not need to enter anything for the web_path
|
||||
; if it is located at http://localhost/music you need to
|
||||
; if it is located at http://localhost/music you need to
|
||||
; set web_path to /music
|
||||
; DEFAULT: ""
|
||||
;web_path = ""
|
||||
|
||||
; The local http url of your server.
|
||||
; If not set, retrieved automatically from server information.
|
||||
; DEFAULT: ""
|
||||
;local_web_path = "http://localhost/ampache"
|
||||
|
||||
;##############################
|
||||
; Session and Login Variables #
|
||||
;##############################
|
||||
|
||||
; Hostname of your database
|
||||
; For socket authentication, set the path to socket file (e.g. /var/run/mysqld/mysqld.sock)
|
||||
; DEFAULT: localhost
|
||||
database_hostname = localhost
|
||||
|
||||
|
@ -50,27 +56,31 @@ database_username = username
|
|||
|
||||
; Password for your ampache database, this can not be blank
|
||||
; this is a 'forced' security precaution, the default value
|
||||
; will not work
|
||||
; will not work (except if using socket authentication)
|
||||
; DEFAULT: ""
|
||||
database_password = password
|
||||
|
||||
; Cryptographic secret
|
||||
; This MUST BE changed with your own secret key. Ampache-specific, just pick any random string you want.
|
||||
secret_key = "abcdefghijklmnoprqstuvwyz0123456"
|
||||
|
||||
; Length that a session will last expressed in seconds. Default is
|
||||
; one hour.
|
||||
; one hour.
|
||||
; DEFAULT: 3600
|
||||
session_length = 3600
|
||||
|
||||
; Length that the session for a single streaming instance will last
|
||||
; the default is two hours. With some clients, and long songs this can
|
||||
; the default is two hours. With some clients, and long songs this can
|
||||
; cause playback to stop, increase this value if you experience that
|
||||
; DEFAULT: 7200
|
||||
stream_length = 7200
|
||||
|
||||
; This length defines how long a 'remember me' session and cookie will
|
||||
; last, the default is 7200, same as length. It is up to the administrator
|
||||
; of the box to increase this, for reference 86400 = 1 day
|
||||
; 604800 = 1 week and 2419200 = 1 month
|
||||
; DEFAULT: 86400
|
||||
remember_length = 86400
|
||||
; This length defines how long a 'remember me' session and cookie will
|
||||
; last, the default is 86400, same as length. It is up to the administrator
|
||||
; of the box to increase this, for reference 86400 = 1 day,
|
||||
; 604800 = 1 week, and 2419200 = 1 month
|
||||
; DEFAULT: 604800
|
||||
remember_length = 604800
|
||||
|
||||
; Name of the Session/Cookie that will sent to the browser
|
||||
; default should be fine
|
||||
|
@ -78,16 +88,16 @@ remember_length = 86400
|
|||
session_name = ampache
|
||||
|
||||
; Lifetime of the Cookie, 0 == Forever (until browser close) , otherwise in terms of seconds
|
||||
; If you want cookies to last past a browser close set this to a value in seconds.
|
||||
; If you want cookies to last past a browser close set this to a value in seconds.
|
||||
; DEFAULT: 0
|
||||
session_cookielife = 0
|
||||
|
||||
; Is the cookie a "secure" cookie? This should only be set to 1 (true) if you are
|
||||
; running a secure site (HTTPS).
|
||||
; running a secure site (HTTPS).
|
||||
; DEFAULT: 0
|
||||
session_cookiesecure = 0
|
||||
|
||||
; Auth Methods
|
||||
; Auth Methods
|
||||
; This defines which auth methods Auth will attempt to use and in which order.
|
||||
; If auto_create isn't enabled the user must exist locally.
|
||||
; DEFAULT: mysql
|
||||
|
@ -108,7 +118,7 @@ auth_methods = "mysql"
|
|||
;auth_password_save = "false"
|
||||
|
||||
; Logout redirection target
|
||||
; Defaults to our own login.php, but we can override it here if, for instance,
|
||||
; Defaults to our own login.php, but we can override it here if, for instance,
|
||||
; we want to redirect to an SSO provider instead.
|
||||
; logout_redirect = "http://sso.example.com/logout"
|
||||
|
||||
|
@ -120,15 +130,15 @@ auth_methods = "mysql"
|
|||
; This defines which file types Ampache will attempt to catalog
|
||||
; You can specify any file extension you want in here separating them
|
||||
; with a |
|
||||
; DEFAULT: mp3|mpc|m4p|m4a|mp4|aac|ogg|rm|wma|asf|flac|spx|ra|ape|shn|wv
|
||||
catalog_file_pattern = "mp3|mpc|m4p|m4a|mp4|aac|ogg|rm|wma|asf|flac|spx|ra|ape|shn|wv"
|
||||
; DEFAULT: mp3|mpc|m4p|m4a|aac|ogg|oga|wav|aif|aiff|rm|wma|asf|flac|opus|spx|ra|ape|shn|wv
|
||||
catalog_file_pattern = "mp3|mpc|m4p|m4a|aac|ogg|oga|wav|aif|aiff|rm|wma|asf|flac|opus|spx|ra|ape|shn|wv"
|
||||
|
||||
; Video Pattern
|
||||
; This defines which video file types Ampache will attempt to catalog
|
||||
; You can specify any file extension you want in here seperating them with
|
||||
; a | but ampache may not be able to parse them
|
||||
; DEAFULT: avi|mpg|flv|m4v|webm
|
||||
catalog_video_pattern = "avi|mpg|flv|m4v|webm"
|
||||
; DEAFULT: avi|mpg|mpeg|flv|m4v|mp4|webm|mkv|wmv|ogv|mov|divx|m2ts
|
||||
catalog_video_pattern = "avi|mpg|mpeg|flv|m4v|mp4|webm|mkv|wmv|ogv|mov|divx|m2ts"
|
||||
|
||||
; Playlist Pattern
|
||||
; This defines which playlist types Ampache will attempt to catalog
|
||||
|
@ -149,11 +159,11 @@ catalog_prefix_pattern = "The|An|A|Die|Das|Ein|Eine|Les|Le|La"
|
|||
; DEFAULT: false
|
||||
;catalog_disable = "false"
|
||||
|
||||
; Use Access List
|
||||
; Use Access List
|
||||
; Toggle this on if you want ampache to pay attention to the access list
|
||||
; and only allow streaming/downloading/api-rpc from known hosts api-rpc
|
||||
; and only allow streaming/downloading/api-rpc from known hosts api-rpc
|
||||
; will not work without this on.
|
||||
; NOTE: Default Behavior is DENY FROM ALL
|
||||
; NOTE: Default Behavior is DENY FROM ALL
|
||||
; DEFAULT: true
|
||||
access_control = "true"
|
||||
|
||||
|
@ -161,7 +171,7 @@ access_control = "true"
|
|||
; If this is set to true ampache will make sure that the URL passed when
|
||||
; attempting to retrieve a song contains a valid Session ID This prevents
|
||||
; others from guessing URL's. This setting is ignored if you have use_auth
|
||||
; disabled.
|
||||
; disabled.
|
||||
; DEFAULT: true
|
||||
require_session = "true"
|
||||
|
||||
|
@ -170,7 +180,7 @@ require_session = "true"
|
|||
; is passed even on hosts defined in the Local Network ACL. This setting
|
||||
; has no effect if access_control is not enabled
|
||||
; DEFAULT: true
|
||||
require_localnet_session = "true"
|
||||
require_localnet_session = "true"
|
||||
|
||||
; Multiple Logins
|
||||
; Added by Vlet 07/25/07
|
||||
|
@ -188,62 +198,63 @@ require_localnet_session = "true"
|
|||
|
||||
; Track User IPs
|
||||
; If this is enabled Ampache will log the IP of every completed login
|
||||
; it will store user,ip,time at one row per login. The results are
|
||||
; it will store user,ip,time at one row per login. The results are
|
||||
; displayed in Admin --> Users
|
||||
; DEFAULT: false
|
||||
;track_user_ip = "false"
|
||||
|
||||
; User IP Cardinality
|
||||
; This defines how many days worth of IP history Ampache will track
|
||||
; As it is one row per login on high volume sites you will want to
|
||||
; clear it every now and then.
|
||||
; As it is one row per login on high volume sites you will want to
|
||||
; clear it every now and then.
|
||||
; DEFAULT: 42 days
|
||||
;user_ip_cardinality = "42"
|
||||
|
||||
; Allow Zip Download
|
||||
; This setting allows/disallows using zlib to zip up an entire
|
||||
; playlist/album for download. Even if this is turned on you will
|
||||
; still need to enabled downloading for the specific user you
|
||||
; still need to enabled downloading for the specific user you
|
||||
; want to be able to use this function
|
||||
; DEFAULT: false
|
||||
;allow_zip_download = "false"
|
||||
|
||||
; File Zip Download
|
||||
; This settings tells Ampache to attempt to save the zip file
|
||||
; to the filesystem instead of creating it in memory, you must
|
||||
; also set tmp_dir_path in order for this to work
|
||||
; DEFAULT: false
|
||||
;file_zip_download = "false"
|
||||
Allow Zip Types
|
||||
; This setting allows/disallows zip download of specific object types
|
||||
; If empty, all supported object types can be zipped.
|
||||
; Otherwise, only the given object list can be zipped.
|
||||
; POSSIBLE VALUES: artist, album, playlist, search, tmp_playlist
|
||||
; DEFAULT: none
|
||||
;allow_zip_types = "album"
|
||||
|
||||
; File Zip Comment
|
||||
; This is an optional configuration option that adds a comment
|
||||
; to your zip files, this only applies if you've got allow_zip_downloads
|
||||
; DEFAULT: Ampache - Zip Batch Download
|
||||
;file_zip_comment = "Ampache - Zip Batch Download"
|
||||
;file_zip_comment = "Ampache - Zip Batch Download"
|
||||
|
||||
; Waveform
|
||||
; This settings tells Ampache to attempt to generate a waveform
|
||||
; for each song. It requires transcode and encode_args_wav settings.
|
||||
; You must also set tmp_dir_path in order for this to work
|
||||
; DEFAULT: false
|
||||
;waveform = "false"
|
||||
;waveform = "false"
|
||||
|
||||
; Waveform color
|
||||
; The waveform color.
|
||||
; DEFAULT: #FF0000
|
||||
;waveform_color = "#FF0000"
|
||||
;waveform_color = "#FF0000"
|
||||
|
||||
; Temporary Directory Path
|
||||
; If File Zip Download or Waveform is enabled this must be set to tell
|
||||
; If Waveform is enabled this must be set to tell
|
||||
; Ampache which directory to save the temporary file to. Do not put a
|
||||
; trailing slash or this will not work.
|
||||
; DEFAULT: false
|
||||
;tmp_dir_path = "false"
|
||||
|
||||
; This setting throttles a persons downloading to the specified
|
||||
; bytes per second. This is not a 100% guaranteed function, and
|
||||
; bytes per second. This is not a 100% guaranteed function, and
|
||||
; you should really use a server based rate limiter if you want
|
||||
; to do this correctly.
|
||||
; to do this correctly.
|
||||
; DEFAULT: off
|
||||
; VALUES: any whole number (in bytes per second)
|
||||
;throttle_download = 10
|
||||
|
@ -261,13 +272,52 @@ getid3_tag_order = "id3v2,id3v1,vorbiscomment,quicktime,matroska,ape,asf,avi,mpe
|
|||
; DEFAULT: false
|
||||
;getid3_detect_id3v2_encoding = "false"
|
||||
|
||||
; This determines if file metadata should be write back to files
|
||||
; as id3 metadata when updated.
|
||||
; DEFAULT: false
|
||||
;write_id3 = "false"
|
||||
|
||||
; This determines if album art should be write back to files
|
||||
; as id3 metadata when updated.
|
||||
; DEFAULT: false
|
||||
;write_id3_art = "false"
|
||||
|
||||
; This determines if catalog manager users can delete medias from disk.
|
||||
; DEFAULT: false
|
||||
;delete_from_disk = "false"
|
||||
|
||||
; This determines the order in which metadata sources are used (and in the
|
||||
; case of plugins, checked)
|
||||
; POSSIBLE VALUES (builtins): filename and getID3
|
||||
; POSSIBLE VALUES (plugins): MusicBrainz, plus any others you've installed.
|
||||
; POSSIBLE VALUES (plugins): MusicBrainz,TheAudioDb, plus any others you've installed.
|
||||
; DEFAULT: getID3 filename
|
||||
metadata_order = "getID3,filename"
|
||||
|
||||
; This determines the order in which metadata sources are used (and in the
|
||||
; case of plugins, checked) for video files
|
||||
; POSSIBLE VALUES (builtins): filename and getID3
|
||||
; POSSIBLE VALUES (plugins): Tvdb,Tmdb,Omdb, plus any others you've installed.
|
||||
; DEFAULT: filename getID3
|
||||
metadata_order_video = "filename,getID3"
|
||||
|
||||
; This determines if extended metadata grabbed from external services should be deferred.
|
||||
; If enabled, extended metadata is retrieved when browsing the library item.
|
||||
; If disabled, extended metadata is retrieved at catalog update.
|
||||
; Today, only Artist information (summary, place formed, ...) can be deferred.
|
||||
; DEFAULT: true
|
||||
deferred_ext_metadata = "true"
|
||||
|
||||
; Some taggers use delimiters other than \0 for fields
|
||||
; This list specifies possible delimiters additional to \0
|
||||
; This setting takes a regex pattern.
|
||||
; DEFAULT: // / \ | , ;
|
||||
additional_genre_delimiters = "[/]{2}|[/|\\\\|\|,|;]"
|
||||
|
||||
; This determines if a preview image should be retrieved from video files
|
||||
; It requires encode_get_image transcode settings.
|
||||
; DEFAULT: false
|
||||
;generate_video_preview = "true"
|
||||
|
||||
; Un comment if don't want ampache to follow symlinks
|
||||
; DEFAULT: false
|
||||
;no_symlinks = "false"
|
||||
|
@ -284,10 +334,10 @@ use_auth = "true"
|
|||
; If use_auth is set to false then this option is used
|
||||
; to determine the permission level of the 'default' users
|
||||
; default is administrator. This setting only takes affect
|
||||
; if use_auth if false
|
||||
; if use_auth is false
|
||||
; POSSIBLE VALUES: user, admin, manager, guest
|
||||
; DEFAULT: admin
|
||||
default_auth_level = "admin"
|
||||
; DEFAULT: guest
|
||||
default_auth_level = "guest"
|
||||
|
||||
; 5 Star Ratings
|
||||
; This allows ratings for almost any object in ampache
|
||||
|
@ -310,14 +360,14 @@ directplay = "true"
|
|||
; Sociable
|
||||
; This turns on / off all of the "social" features of ampache
|
||||
; default is on, but if you don't care and just want music
|
||||
; turn this off to disable all social features.
|
||||
; turn this off to disable all social features.
|
||||
; DEFAULT: true
|
||||
sociable = "true"
|
||||
|
||||
; Notify
|
||||
; This turns on / off all Ampache notifications
|
||||
; DEFAULT: true
|
||||
notify = "true"
|
||||
; License
|
||||
; This turns on / off all licensing features on Ampache
|
||||
; DEFAULT: false
|
||||
;licensing = "false"
|
||||
|
||||
; This options will turn on/off Demo Mode
|
||||
; If Demo mode is on you can not play songs or update your catalog
|
||||
|
@ -332,7 +382,7 @@ notify = "true"
|
|||
; requirments on larger catalogs. If you have the memory this can create
|
||||
; a 2-3x speed improvement.
|
||||
; DEFAULT: false
|
||||
;memory_cache = false
|
||||
;memory_cache = "false"
|
||||
|
||||
; Memory Limit
|
||||
; This defines the "Min" memory limit for PHP if your php.ini
|
||||
|
@ -347,7 +397,43 @@ notify = "true"
|
|||
; Especially useful if you have a front and a back image in a folder
|
||||
; comment out if ampache should search for any jpg,gif or png
|
||||
; DEFAULT: folder.jpg
|
||||
;album_art_preferred_filename = "folder.jpg"
|
||||
;album_art_preferred_filename = "folder.jpg"
|
||||
|
||||
; Album Art Store on Disk
|
||||
; This defines if arts should be stored on disk instead of database.
|
||||
; DEFAULT: false
|
||||
;album_art_store_disk = "false"
|
||||
|
||||
; Local Metadata Directory
|
||||
; This define a local metadata directory with write access where to store
|
||||
; heavy data if enabled (album arts, ...)
|
||||
; DEFAULT: none
|
||||
;local_metadata_dir = "/metadata"
|
||||
|
||||
; Maximal upload size
|
||||
; Specify the maximal allowed upload size for images, in bytes.
|
||||
; DEFAULT: 1048576
|
||||
;max_upload_size = 1048576
|
||||
|
||||
; Album Art Minimum Width
|
||||
; Specify the minimum width for arts (in pixel).
|
||||
; DEFAULT: none
|
||||
;album_art_min_width = 100
|
||||
|
||||
; Album Art Maximum Width
|
||||
; Specify the maximum width for arts (in pixel).
|
||||
; DEFAULT: none
|
||||
;album_art_max_width = 1024
|
||||
|
||||
; Album Art Minimum Height
|
||||
; Specify the minimum height for arts (in pixel).
|
||||
; DEFAULT: none
|
||||
;album_art_min_height = 100
|
||||
|
||||
; Album Art Maximum Height
|
||||
; Specify the maximum height for arts (in pixel).
|
||||
; DEFAULT: none
|
||||
;album_art_max_height = 1024
|
||||
|
||||
; Resize Images * Requires PHP-GD *
|
||||
; Set this to true if you want Ampache to resize the Album
|
||||
|
@ -357,25 +443,23 @@ notify = "true"
|
|||
; DEFAULT: false
|
||||
;resize_images = "false"
|
||||
|
||||
; Statistical Graphs * Requires PHP-GD *
|
||||
; Set this to true if you want Ampache to generate statistical
|
||||
; graphs on usages / users.
|
||||
; DEFAULT: false
|
||||
;statistical_graphs = "false"
|
||||
|
||||
; Art Gather Order
|
||||
; Simply arrange the following in the order you would like
|
||||
; ampache to search. If you want to disable one of the search
|
||||
; methods simply leave it out. DB should be left as the first
|
||||
; method unless you want it to overwrite what's already in the
|
||||
; database
|
||||
; POSSIBLE VALUES: db tags folder amazon lastfm musicbrainz google
|
||||
; POSSIBLE VALUES (builtins): db tags folder lastfm musicbrainz google
|
||||
; POSSIBLE VALUES (plugins): Amazon,TheAudioDb,Tmdb,Omdb,Flickr
|
||||
; DEFAULT: db,tags,folder,musicbrainz,lastfm,google
|
||||
art_order = "db,tags,folder,musicbrainz,lastfm,google"
|
||||
|
||||
; Amazon Developer Key
|
||||
; These are needed in order to actually use the amazon album art
|
||||
; Your public key is your 'Access Key ID'
|
||||
; Your private key is your 'Secret Access Key'
|
||||
; DEFAULT: false
|
||||
;amazon_developer_public_key = ""
|
||||
;amazon_developer_private_key = ""
|
||||
;amazon_developer_associate_tag = ""
|
||||
|
||||
; Recommendations
|
||||
; Set this to true to enable display of similar artists or albums
|
||||
; while browsing. Requires Last.FM.
|
||||
|
@ -390,14 +474,14 @@ art_order = "db,tags,folder,musicbrainz,lastfm,google"
|
|||
|
||||
; Last.FM API Key
|
||||
; Set this to your Last.FM api key to actually use Last.FM for
|
||||
; recommendations.
|
||||
;lastfm_api_key = ""
|
||||
; recommendations and metadata.
|
||||
lastfm_api_key = "d5df942424c71b754e54ce1832505ae2"
|
||||
|
||||
; Wanted
|
||||
; Set this to true to enable display missing albums and the
|
||||
; possibility for users to mark it as wanted.
|
||||
; DEFAULT: false
|
||||
;wanted = "false"
|
||||
wanted = "true"
|
||||
|
||||
; Wanted types
|
||||
; Set the allowed types of wanted releases (album,compilation,single,ep,live,remix,promotion,official)
|
||||
|
@ -413,43 +497,34 @@ wanted_types = "album,official"
|
|||
; EchoNest provides several music services. Currently used for missing song 30 seconds preview.
|
||||
;echonest_api_key = ""
|
||||
|
||||
; Labels
|
||||
; Use labels to browse artists per label membership.
|
||||
; DEFAULT: false
|
||||
;label = "false"
|
||||
|
||||
; Broadcasts
|
||||
; Allow users to broadcast music.
|
||||
; This feature requires advanced server configuration, please take a look on the wiki for more information.
|
||||
; DEFAULT: false
|
||||
;broadcast = "false"
|
||||
|
||||
; Channels
|
||||
; Set this to true to enable channels and the
|
||||
; possibility for users to create channels from playlists
|
||||
; DEFAULT: true
|
||||
channel = "true"
|
||||
|
||||
; Live Streams
|
||||
; Set this to true to enable live streams (radio) and the
|
||||
; possibility for users to add new live streams.
|
||||
; DEFAULT: true
|
||||
live_stream = "true"
|
||||
|
||||
; Web Socket address
|
||||
; Declare the web socket server address
|
||||
; DEFAULT: determined automatically
|
||||
;websocket_address = "ws://localhost:8100"
|
||||
|
||||
; Amazon base urls
|
||||
; An array of Amazon sites to search.
|
||||
; NOTE: This will search each of these sites in turn so don't expect it
|
||||
; to be lightning fast!
|
||||
; It is strongly recommended that only one of these is selected at any
|
||||
; one time
|
||||
; POSSIBLE VALUES:
|
||||
; http://webservices.amazon.com
|
||||
; http://webservices.amazon.co.uk
|
||||
; http://webservices.amazon.de
|
||||
; http://webservices.amazon.co.jp
|
||||
; http://webservices.amazon.fr
|
||||
; http://webservices.amazon.ca
|
||||
; Default: http://webservices.amazon.com
|
||||
amazon_base_urls = "http://webservices.amazon.com"
|
||||
|
||||
; max_amazon_results_pages
|
||||
; The maximum number of results pages to pull from EACH amazon site
|
||||
; NOTE: The art search pages through the results returned by your search
|
||||
; up to this number of pages. As with the base_urls above, this is going
|
||||
; to take more time, the more pages you ask it to process.
|
||||
; Of course a good search will return only a few matches anyway.
|
||||
; It is strongly recommended that you do _not_ change this value
|
||||
; DEFAULT: 1 page (10 items)
|
||||
max_amazon_results_pages = 1
|
||||
|
||||
; Debug
|
||||
; If this is enabled Ampache will write debugging information to the log file
|
||||
; DEFAULT: false
|
||||
|
@ -458,7 +533,7 @@ max_amazon_results_pages = 1
|
|||
; Debug Level
|
||||
; This should always be set in conjunction with the
|
||||
; debug option, it defines how prolific you want the
|
||||
; debugging in ampache to be. values are 1-5.
|
||||
; debugging in ampache to be. values are 1-5.
|
||||
; 1 == Errors only
|
||||
; 2 == Error + Failures (login attempts etc.)
|
||||
; 3 == ??
|
||||
|
@ -487,7 +562,7 @@ log_filename = "%name.%Y%m%d.log"
|
|||
; DEFAULT: UTF-8
|
||||
site_charset = UTF-8
|
||||
|
||||
; Locale Charset
|
||||
; Locale Charset
|
||||
; Local charset (mainly for file operations) if different
|
||||
; from site_charset.
|
||||
; This is disabled by default, enable only if needed
|
||||
|
@ -496,12 +571,19 @@ site_charset = UTF-8
|
|||
;lc_charset = "ISO8859-1"
|
||||
|
||||
; Refresh Limit
|
||||
; This defines the default refresh limit in seconds for
|
||||
; This defines the default refresh limit in seconds for
|
||||
; pages with dynamic content, such as now playing
|
||||
; DEFAULT: 60
|
||||
; Possible Values: Int > 5
|
||||
refresh_limit = "60"
|
||||
|
||||
; Footer Statistics
|
||||
; This defines whether statistics (Queries, Cache Hits, Load Time)
|
||||
; are shown in the page footer.
|
||||
; DEFAULT: true
|
||||
; Possible values: true, false
|
||||
show_footer_statistics = "true"
|
||||
|
||||
;#########################################################
|
||||
; Custom actions (optional) #
|
||||
;#########################################################
|
||||
|
@ -528,10 +610,10 @@ refresh_limit = "60"
|
|||
;#########################################################
|
||||
|
||||
; LDAP filter string to use (required)
|
||||
; For OpenLDAP use "uid"
|
||||
; For OpenLDAP use "uid"
|
||||
; For Microsoft Active Directory (MAD) use "sAMAccountName"
|
||||
; DEFAULT: null
|
||||
; ldap_filter = "sAMAccountName"
|
||||
;ldap_filter = "(sAMAccountName=%v)"
|
||||
|
||||
; LDAP objectclass (required)
|
||||
; OpanLDAP objectclass = "*"
|
||||
|
@ -608,15 +690,15 @@ refresh_limit = "60"
|
|||
; DEFAULT: false
|
||||
;admin_enable_required = "false"
|
||||
|
||||
; This setting will allow all registrants/ldap/http users
|
||||
; to be auto-approved as a user. By default, they will be
|
||||
; This setting will allow all registrants/ldap/http users
|
||||
; to be auto-approved as a user. By default, they will be
|
||||
; added as a guest and must be promoted by the admin.
|
||||
; POSSIBLE VALUES: guest, user, admin
|
||||
; DEFAULT: guest
|
||||
;auto_user = "guest"
|
||||
|
||||
; This will display the user agreement when registering
|
||||
; For agreement text, edit templates/user_agreement.php
|
||||
; For agreement text, edit config/registration_agreement.php
|
||||
; User will need to accept the agreement before they can register
|
||||
; DEFAULT: false
|
||||
;user_agreement = "false"
|
||||
|
@ -625,6 +707,24 @@ refresh_limit = "60"
|
|||
; DEFAULT: false
|
||||
;user_no_email_confirm = "false"
|
||||
|
||||
; This will display the cookie disclaimer (EU Cookie Law)
|
||||
; DEFAULT: false
|
||||
;cookie_disclaimer = "false"
|
||||
|
||||
; The fields that will be shown on Registration page
|
||||
; If a user wants to register.
|
||||
; Username and email fields are forced.
|
||||
; POSSIBLE VALUES: fullname,website,state,city
|
||||
; DEFAULT: "fullname,website"
|
||||
registration_display_fields = "fullname,website"
|
||||
|
||||
; The fields that will be mandatory
|
||||
; This controls which fields are mandatory for registration.
|
||||
; Username and email fields are forced mandatory.
|
||||
; POSSIBLE VALUES: fullname,website,state,city
|
||||
; DEFAULT: fullname
|
||||
registration_mandatory_fields = "fullname"
|
||||
|
||||
;########################################################
|
||||
; These options control the dynamic downsampling based #
|
||||
; on current usage #
|
||||
|
@ -646,7 +746,7 @@ refresh_limit = "60"
|
|||
|
||||
;######################################################
|
||||
; These are commands used to transcode non-streaming
|
||||
; formats to the target file type for streaming.
|
||||
; formats to the target file type for streaming.
|
||||
; This can be useful in re-encoding file types that don't stream
|
||||
; very well, or if your player doesn't support some file types.
|
||||
;
|
||||
|
@ -662,25 +762,64 @@ refresh_limit = "60"
|
|||
; (e.g. if you store everything in FLAC, but don't want to ever stream that.)
|
||||
; transcode_TYPE = {allowed|required|false}
|
||||
; DEFAULT: false
|
||||
;;; Audio
|
||||
;transcode_m4a = allowed
|
||||
;transcode_flac = required
|
||||
;transcode_mpc = required
|
||||
;transcode_ogg = required
|
||||
;transcode_oga = required
|
||||
;transcode_wav = required
|
||||
;transcode_wma = required
|
||||
;transcode_aif = required
|
||||
;transcode_aiff = required
|
||||
;transcode_ape = required
|
||||
;transcode_shn = required
|
||||
;transcode_mp3 = allowed
|
||||
;;; Video
|
||||
;transcode_avi = allowed
|
||||
;transcode_mkv = allowed
|
||||
;transcode_mpg = allowed
|
||||
;transcode_mpeg = allowed
|
||||
;transcode_m4v = allowed
|
||||
;transcode_mp4 = allowed
|
||||
;transcode_mov = allowed
|
||||
;transcode_wmv = allowed
|
||||
;transcode_ogv = allowed
|
||||
;transcode_divx = allowed
|
||||
;transcode_m2ts = allowed
|
||||
;transcode_webm = allowed
|
||||
|
||||
; Default output format
|
||||
; Default audio output format
|
||||
; DEFAULT: none
|
||||
;encode_target = mp3
|
||||
|
||||
; Default video output format
|
||||
; DEFAULT: none
|
||||
;encode_video_target = webm
|
||||
|
||||
; Override the default output format on a per-type basis
|
||||
; encode_target_TYPE = TYPE
|
||||
; DEFAULT: none
|
||||
;encode_target_flac = ogg
|
||||
|
||||
; Override the default TYPE transcoding behavior on a per-player basis
|
||||
; transcode_player_PLAYER_TYPE = TYPE
|
||||
; Valid PLAYER is: webplayer, api
|
||||
; DEFAULT: none
|
||||
;transcode_player_webplayer_m4a = required
|
||||
;transcode_player_webplayer_flac = required
|
||||
;transcode_player_webplayer_mpc = required
|
||||
|
||||
; Override the default output format on a per-player basis
|
||||
; encode_player_PLAYER_target = TYPE
|
||||
; Valid PLAYER is: webplayer, api
|
||||
; DEFAULT: none
|
||||
;encode_player_webplayer_target = mp3
|
||||
;encode_player_api_target = mp3
|
||||
|
||||
; Allow clients to override transcode settings (output type, bitrate, codec ...)
|
||||
; DEFAULT: true
|
||||
transcode_player_customize = true
|
||||
transcode_player_customize = "true"
|
||||
|
||||
; Command configuration. Substitutions will be made as follows:
|
||||
; %FILE% => filename
|
||||
|
@ -694,13 +833,16 @@ transcode_player_customize = true
|
|||
; equivalent to the old default, but if you find that necessary you should be
|
||||
; clever enough to figure out how on your own.
|
||||
; DEFAULT: none
|
||||
;transcode_cmd = "ffmpeg -i %FILE%"
|
||||
;transcode_cmd = "avconv -i %FILE%"
|
||||
;transcode_cmd = "/usr/bin/neatokeen %FILE%"
|
||||
;transcode_cmd = "ffmpeg"
|
||||
;transcode_cmd = "avconv"
|
||||
;transcode_cmd = "/usr/bin/neatokeen"
|
||||
|
||||
; Transcode input file argument
|
||||
transcode_input = "-i %FILE%"
|
||||
|
||||
; Specific transcode commands
|
||||
; It shouldn't be necessary in most cases, but you can override the transcode
|
||||
; command for specific source formats. It still needs to accept the
|
||||
; command for specific source formats. It still needs to accept the
|
||||
; encoding arguments, so the easiest approach is to use your normal command as
|
||||
; a clearing-house.
|
||||
; transcode_cmd_TYPE = TRANSCODE_CMD
|
||||
|
@ -708,12 +850,28 @@ transcode_player_customize = true
|
|||
|
||||
; Encoding arguments
|
||||
; For each output format, you should provide the necessary arguments for
|
||||
; your transcode_cmd.
|
||||
; your transcode_cmd.
|
||||
; encode_args_TYPE = TRANSCODE_CMD_ARGS
|
||||
;encode_args_mp3 = "-vn -b:a %SAMPLE%K -c:a libmp3lame -f mp3 pipe:1"
|
||||
;encode_args_ogg = "-vn -b:a %SAMPLE%K -c:a libvorbis -f ogg pipe:1"
|
||||
;encode_args_m4a = "-vn -b:a %SAMPLE%K -c:a libfdk_aac -f adts pipe:1"
|
||||
;encode_args_wav = "-vn -b:a %SAMPLE%K -c:a pcm_s16le -f wav pipe:1"
|
||||
encode_args_mp3 = "-vn -b:a %SAMPLE%K -c:a libmp3lame -f mp3 pipe:1"
|
||||
encode_args_ogg = "-vn -b:a %SAMPLE%K -c:a libvorbis -f ogg pipe:1"
|
||||
encode_args_m4a = "-vn -b:a %SAMPLE%K -c:a libfdk_aac -f adts pipe:1"
|
||||
encode_args_wav = "-vn -b:a %SAMPLE%K -c:a pcm_s16le -f wav pipe:1"
|
||||
encode_args_flv = "-b:a %SAMPLE%K -ar 44100 -ac 2 -v 0 -f flv -c:v libx264 -preset superfast -threads 0 pipe:1"
|
||||
encode_args_webm = "-q %QUALITY% -f webm -c:v libvpx -maxrate %MAXBITRATE%k -preset superfast -threads 0 pipe:1"
|
||||
encode_args_ts = "-q %QUALITY% -s %RESOLUTION% -f mpegts -c:v libx264 -c:a libmp3lame -maxrate %MAXBITRATE%k -preset superfast -threads 0 pipe:1"
|
||||
|
||||
; Encoding arguments to retrieve an image from a single frame
|
||||
encode_get_image = "-ss %TIME% -f image2 -vframes 1 pipe:1"
|
||||
|
||||
; Encoding argument to encrust subtitle
|
||||
encode_srt = "-vf \"subtitles='%SRTFILE%'\""
|
||||
|
||||
; Encode segment frame argument
|
||||
encode_ss_frame = "-ss %TIME%"
|
||||
|
||||
; Encode segment duration argument
|
||||
encode_ss_duration = "-t %DURATION%"
|
||||
|
||||
|
||||
;######################################################
|
||||
; these options allow you to configure your rss-feed
|
||||
|
@ -721,7 +879,7 @@ transcode_player_customize = true
|
|||
; song is the information in the feed. can be multiple items.
|
||||
; use_rss = false (values true | false)
|
||||
;DEFAULT: use_rss = false
|
||||
;use_rss = false
|
||||
;use_rss = "false"
|
||||
;#####################################################
|
||||
|
||||
;#############################
|
||||
|
@ -737,7 +895,7 @@ transcode_player_customize = true
|
|||
|
||||
; If Ampache is behind an https reverse proxy, force use HTTPS protocol.
|
||||
;Default: false
|
||||
;force_ssl = true
|
||||
;force_ssl = "true"
|
||||
|
||||
;#############################
|
||||
; Mail Settings #
|
||||
|
@ -749,7 +907,7 @@ transcode_player_customize = true
|
|||
;mail_type = "php"
|
||||
|
||||
;Mail domain.
|
||||
;DEFAULT: example.com
|
||||
;DEFAULT: example.com
|
||||
;mail_domain = "example.com"
|
||||
|
||||
;This will be combined with mail_domain and used as the source address for
|
||||
|
@ -796,7 +954,7 @@ transcode_player_customize = true
|
|||
|
||||
;Enable SMTP authentication
|
||||
;DEFAULT: false
|
||||
;mail_auth = true
|
||||
;mail_auth = "true"
|
||||
|
||||
;SMTP Username
|
||||
;your mail auth username.
|
||||
|
|
29
sources/cookie_disclaimer.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
|
||||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
require_once 'lib/init.php';
|
||||
|
||||
UI::show_header();
|
||||
|
||||
require_once AmpConfig::get('prefix') . '/templates/cookie_disclaimer.inc.php';
|
||||
|
||||
UI::show_footer();
|
6
sources/daap/.htaccess
Normal file
|
@ -0,0 +1,6 @@
|
|||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-s
|
||||
RewriteRule ^(.+)$ /index.php?action=$1 [PT,L,QSA]
|
||||
</IfModule>
|
67
sources/daap/index.php
Normal file
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
|
||||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
define('NO_SESSION','1');
|
||||
require_once '../lib/init.php';
|
||||
|
||||
if (!AmpConfig::get('daap_backend')) {
|
||||
echo "Disabled.";
|
||||
exit;
|
||||
}
|
||||
|
||||
$action = $_GET['action'];
|
||||
|
||||
$headers = apache_request_headers();
|
||||
//$daapAccessIndex = $headers['Client-DAAP-Access-Index'];
|
||||
//$daapVersion = $headers['Client-DAAP-Version'];
|
||||
//$daapValidation = $headers['Client-DAAP-Validation']; // That's header hash, we don't care about it (only required by iTunes >= 7.0)
|
||||
debug_event('daap', 'Request headers: '. print_r($headers, true), '5');
|
||||
|
||||
// Get the list of possible methods for the Plex API
|
||||
$methods = get_class_methods('daap_api');
|
||||
// Define list of internal functions that should be skipped
|
||||
$internal_functions = array('apiOutput', 'create_dictionary', 'createError', 'output_body', 'output_header', 'follow_stream');
|
||||
|
||||
Daap_Api::create_dictionary();
|
||||
|
||||
$params = array_filter(explode('/', $action), 'strlen');
|
||||
if (count($params) > 0) {
|
||||
// Recurse through them and see if we're calling one of them
|
||||
for ($i = count($params); $i > 0; $i--) {
|
||||
$act = strtolower(implode('_', array_slice($params, 0, $i)));
|
||||
$act = str_replace("-", "_", $act);
|
||||
foreach ($methods as $method) {
|
||||
if (in_array($method, $internal_functions)) { continue; }
|
||||
|
||||
// If the method is the same as the action being called
|
||||
// Then let's call this function!
|
||||
if ($act == $method) {
|
||||
call_user_func(array('daap_api', $method), array_slice($params, $i, count($params) - $i));
|
||||
// We only allow a single function to be called, and we assume it's cleaned up!
|
||||
exit();
|
||||
}
|
||||
|
||||
} // end foreach methods in API
|
||||
}
|
||||
}
|
||||
|
||||
Daap_Api::createError(404);
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
|
|
@ -22,4 +22,12 @@ Acknowledgements
|
|||
* Randy Perkins
|
||||
* Ben Shields
|
||||
* Afterster
|
||||
* SUTJael
|
||||
* SUTJael
|
||||
* Psy-Virus
|
||||
* John Moore (jcwmoore)
|
||||
* René Bigler (Razrael)
|
||||
* Kaivo
|
||||
* Ernest Wagner (wagnered)
|
||||
* lotan
|
||||
* brownl
|
||||
* Deathcow
|
|
@ -1,7 +1,207 @@
|
|||
CHANGELOG
|
||||
=========
|
||||
|
||||
3.7
|
||||
3.8.0
|
||||
----------
|
||||
- Added Portuguese (Brasil) language (thanks Ione Souza Junior)
|
||||
- Updated PHPMailer version to 5.2.10
|
||||
- Fixed user stats clear
|
||||
- Added user, followers and last shouts XML API functions
|
||||
- Fixed transcoded process end on some systems (thanks nan4k7)
|
||||
- Added ogg channel streaming support (thanks Deathcow)
|
||||
- Fixed sql connection close before stream (thanks fufroma)
|
||||
- Added support for several ldap filters (thanks T-Rock)
|
||||
- Fixed 'Add to existing playlist' button on web player (thanks RyanCopley)
|
||||
- Added 'add to existing playlist' link on album page (thanks RyanCopley)
|
||||
- Added option to hide user fullname from other users
|
||||
- Added playlist track information in Apache XML API (thanks RyanCopley)
|
||||
- Fixed playlist remove song in Apache XML API (thanks RyanCopley)
|
||||
- Fixed SubSonic API ifModifiedSince information
|
||||
- Added Podcast links to albums / artists
|
||||
- Added Piwik and Google Analytics plugins
|
||||
- Added Apache 2.4 access control declaration in htaccess files
|
||||
- Fixed performance issues on user preferences
|
||||
- Added artist search by year and place
|
||||
- Fixed search by comment (thanks malkavi)
|
||||
- Added Paypal and Flattr plugins
|
||||
- Added .maintenance page
|
||||
- Fixed captcha
|
||||
- Added private messages between users
|
||||
- Fixed SubSonic API rating information on albums and songs
|
||||
- Added latest artists and shouts RSS feeds
|
||||
- Fixed tag cloud ordering
|
||||
- Added Label entities associated to artists / users
|
||||
- Added WebDAV backend
|
||||
- Fixed SubSonic API requests with musicFolderId parameter (thanks dhsc19)
|
||||
- Added footer text edition setting
|
||||
- Added uploaded artist list on user page
|
||||
- Added custom Ampache login logo and favicon support
|
||||
- Added edition support on shared objects (thanks dhsc19)
|
||||
- Fixed share feature on videos (thanks RobertoCarlo)
|
||||
- Removed album year display from album name if unset
|
||||
- Fixed Subsonic API Album/Artist song's link (thanks dhsc19 and daneren2005)
|
||||
- Added mysql database socket authentication support on web setup (thanks AsavarTzeth)
|
||||
- Fixed artist art url for mobile use (thanks dhsc19)
|
||||
- Added Shoutbox home plugin
|
||||
- Added catalog favorites home plugin
|
||||
- Fixed search by rating (thanks iamnumbersix)
|
||||
- Added UPnP localplay (thanks SeregaPru)
|
||||
- Changed preferences to return the global value if preference is missing for the searched user
|
||||
- Fixed special chars in songs names and tags (thanks SeregaPru)
|
||||
- Fixed Subsonic API playlist edition/delation (thanks dhsc19)
|
||||
- Fixed integer default value in Apache XML API
|
||||
- Fixed image thumb on webplayer and search preview (thanks RobertoCarlo and eephyne)
|
||||
- Fixed proxy setting on all external http requests (thanks brendankearney)
|
||||
- Added QRCode view of user API key
|
||||
- Fixed http status code on Subsonic API streams when using curl (thanks nicklan)
|
||||
- Added Server-Sent Events on catalog actions
|
||||
- Added option to enable/disable channel and live stream features
|
||||
- Removed official PHP 5.3 support
|
||||
- Added option to show/hide footer statistics (thanks brownl)
|
||||
- Added delete from disk option on user uploaded files
|
||||
- Added installation type and players helper at installation process
|
||||
- Added tv_episode tag on quicktime files (thanks wagnered)
|
||||
- Added new option to disable deferred extended metadata, e.g. artist details
|
||||
- Added Subsonic API getAvatar function
|
||||
- Fixed unsynced lyrics tags
|
||||
- Fixed ldap_filter setting deactivation on ampache.cfg.php update (thanks Rouzax)
|
||||
- Added Subsonic API similar artists & songs functions
|
||||
- Added Subsonic API getLyrics function
|
||||
- Fixed disk number and album artist metadata on quicktime files (thanks JoeDat)
|
||||
- Fixed Ampache API playlist_add_song function
|
||||
- Added ability to store images on disk
|
||||
- Added new setting to define album art min and max width/height
|
||||
- Fixed Subsonic API getAlbum returned artist id on songs
|
||||
- Fixed Subsonic API cover art when PHP-GD unavailable
|
||||
- Fixed localplay playlist refresh on volume changes (thanks essagl)
|
||||
- Fixed web player equalizer option if visualizer is not enabled (thanks brownl)
|
||||
- Fixed asx file mime type (thanks thinca)
|
||||
- Added song genre parsing options (thanks Razrael and lotan)
|
||||
- Added sort on languages list (thanks brownl)
|
||||
- Added placeholder text to search box (thanks brownl)
|
||||
- Added web player Play Next feature (thanks tan-ce)
|
||||
- Fixed Plex backend administration page uri (thanks a9k)
|
||||
- Fixed expired shared objects clean (thanks eephyne)
|
||||
- Added missing artist search results (thanks bliptec)
|
||||
- Fixed song genre id parsing (thanks lotan)
|
||||
- Added Scrobble method to Subsonic API
|
||||
- Added an option to add tags to child without overwriting
|
||||
- Added image dimension info to image tables (thanks tsquare66)
|
||||
- Replaced ArchiveLib by StreamZip-PHP to avoid temporary zip file
|
||||
- Added Year field in song details and edition
|
||||
- Added Subsonic API create/delete user, jukebox control and search auto suggestion
|
||||
- Added few optional install tests
|
||||
- Improved Share features with modal dialog choices
|
||||
- Added new action on playlists to remove duplicates
|
||||
- Fixed playlist addition to another playlist (thanks kszulc)
|
||||
- Fixed Various Artist link on album page (thanks Jucgshu)
|
||||
- Added session_destroy call when a session should be destroyed
|
||||
- Added HTML5 ReplayGain track feature
|
||||
- Added display and mandatory user registration fields settings
|
||||
- Added .htaccess IfModule mod_access.c directives
|
||||
- Fixed SmartPlayer results per user (thanks nakinigit)
|
||||
- Fixed XSS vulnerability CVE-2014-8620 (thanks g0blin)
|
||||
- Fixed playlist import setting on catalog update to be disabled by default (thanks DaPike)
|
||||
- Added ability to browse my tags other library items than songs
|
||||
- Added Stream Control plugins
|
||||
- Added transcode settings per player type
|
||||
- Added ability to write directly the new configuration file when it version changed
|
||||
- Added `quick play url` to have permanent authenticated stream link without session
|
||||
- Fixed unresponsive website on batch download (thanks Rouzax)
|
||||
- Added batch download item granularity
|
||||
- Fixed 'guest' user site rendering
|
||||
- Added Aurora.js support in webplayer
|
||||
- Added Google Maps geolocation analyze plugin
|
||||
- Added statistical graphs
|
||||
- Added user geolocation
|
||||
- Added 'Missing Artist' search
|
||||
- Fixed Ampache installation with FastCGI
|
||||
- Added a new RSS Feed plugin
|
||||
- Added a new 'display home' plugin type
|
||||
- Added Favorite and Rating features to playlists
|
||||
- Added user feedback near mouse cursor on democratic votes
|
||||
- Changed header page position to be fixed
|
||||
- Added external links on song page details
|
||||
- Fixed Subsonic API getAlbumList2 byGenre and byYear order (thanks rrjk)
|
||||
- Added html5 desktop notification
|
||||
- Added album group order setting
|
||||
- Fixed unwanted album merge when one of the album doesn't have mbid
|
||||
- Changed video player to go outside the footer
|
||||
- Added ip address in authentication failure for fail2ban scripts (thanks popindavibe)
|
||||
- Added parameter to hide directplay button if number of items is above a limit
|
||||
- Added Tag split (thanks jcwmoore)
|
||||
- Fixed album/artist arts and stats migration on rename (thanks jcwmoore)
|
||||
- Fixed get lyrics from files (thanks apastuszak)
|
||||
- Fixed verify local catalog (thanks JoeDat)
|
||||
- Removed Twitter code
|
||||
- Added optional cookie disclaimer for the EU Cookie Law
|
||||
- Replaced catalog action links to action dropdown list (thanks Psy-Virus)
|
||||
- Fixed `remember me` feature (thanks ainola)
|
||||
- Added email when registered user must be enabled by administrators
|
||||
- Fixed local catalog clean on Windows (thanks Rouzax)
|
||||
- Added Subsonic API maxBitRate parameter support (thanks philipl)
|
||||
- Fixed SubSonic API special characters encode (thanks nan4k7)
|
||||
- Added Beets local and remote catalog support (thanks Razrael)
|
||||
- Fixed XML error code returned with invalid Ampache API handshake (thanks funkygaddafi)
|
||||
- Replaced iframe to Ajax dynamic page loading
|
||||
- Changed `Albums of the moment` to not necessarily have a cover
|
||||
- Added Plex backend items edition support
|
||||
- Added hls stream support
|
||||
- Added X-Content-Duration header support on streams
|
||||
- Removed Toogle Art from artist page
|
||||
- Fixed track numbers when removing a song from playlist (thanks stonie08)
|
||||
- Added Plex backend playlist support
|
||||
- Added gather art from video files (thanks wagnered)
|
||||
- Added Plex backend movie / tvshow support
|
||||
- Added release group on albums
|
||||
- Added Smart Playlist songs list
|
||||
- Added zlib test
|
||||
- Removed old Ampache themes
|
||||
- Fixed SubSonic API lastModified element (thanks bikkuri10)
|
||||
- Disabled `beautiful url` on XML-API for retro-compatibility
|
||||
- Fixed image resource allocation (thanks greengeek1)
|
||||
- Added setting to write id3 metadata to files (thanks tsquare66)
|
||||
- Added check for large files manipulation
|
||||
- Added video subtitle support
|
||||
- Fixed Google arts to use real arts and not the small size preview
|
||||
- Added Tmdb metadata plugin
|
||||
- Added Omdb metadata plugin
|
||||
- Added Music Clips, Movies and TV Shows support
|
||||
- Added media type information on catalog
|
||||
- Fixed get SmartPlaylist in XML-API (thanks opencrf)
|
||||
- Added beautiful url on arts
|
||||
- Improved browse list header (thanks Psy-Virus)
|
||||
- Fixed user online/offline information on Reborn theme (thanks thorsforge)
|
||||
- Added UPnP backend (thanks SeregaPru)
|
||||
- Added DAAP backend
|
||||
- Added sort options on playlists (thanks Shdwdrgn)
|
||||
- Fixed XML-API tag information (thanks jcwmoore)
|
||||
- Fixed multiple broadcast play (thanks uk3gaus)
|
||||
- Added SmartPlaylists to Subsonic API
|
||||
- Added limit option on SmartPlaylists
|
||||
- Added random option on SmartPlaylists
|
||||
- Added 'item count' on browse
|
||||
- Added direct typed links on items tags
|
||||
- Fixed SubSonic API compatibility with few players requesting information on library -1
|
||||
- Added license information on songs
|
||||
- Added upload feature on web interface
|
||||
- Added albumartist information on songs (thanks tsquare66)
|
||||
- Fixed errors on sql table exists check
|
||||
- Fixed play/pause on broadcasts (thanks uk3gaus)
|
||||
- Added donation button
|
||||
- Added democratic page automatic refresh
|
||||
- Fixed distinct random albums
|
||||
- Added collapsing menu (thanks Kaivo)
|
||||
- Added 'save to playlist' feature on web player (thanks Kaivo)
|
||||
- Added tag merge feature
|
||||
- Fixed democratic vote with automatic logins (thanks M4DM4NZ)
|
||||
- Added git pull update from web interface for development versions
|
||||
- Fixed http-rang requests on streaming (thanks thejk)
|
||||
- Improved installation process
|
||||
- Improved French translation (thanks arnaudbey)
|
||||
- Improved German translation (thanks Psy-Virus and meandor)
|
||||
|
||||
3.7.0
|
||||
----------
|
||||
- Added Scrutinizer analyze
|
||||
- Fixed playlist play with disabled songs (reported by stebe)
|
||||
|
|
|
@ -27,9 +27,15 @@ should be implemented as a public method:
|
|||
get_metadata(Array $metadata)
|
||||
The passed array contains the best metadata we've got.
|
||||
save_rating(Rating $rating, int $new_value)
|
||||
save_songplay(Song $song)
|
||||
save_mediaplay(Media $media)
|
||||
get_lyrics(Song $song)
|
||||
process_wanted(Wanted $wanted)
|
||||
shortener(string $url)
|
||||
get_photos(string $search)
|
||||
|
||||
gather_arts(string $type, array $options, int $limit)
|
||||
get_song_preview(string $track_mbid, string $artist_name, string $title)
|
||||
stream_song_preview(string $file)
|
||||
display_home()
|
||||
external_share(string $url, string $text)
|
||||
display_user_field(library_item $libitem = null)
|
||||
display_on_footer
|
69
sources/graph.php
Normal file
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
|
||||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
// This file is a little weird it needs to allow API session
|
||||
// this needs to be done a little better, but for now... eah
|
||||
define('NO_SESSION','1');
|
||||
require_once 'lib/init.php';
|
||||
|
||||
// Check to see if they've got an interface session or a valid API session, if not GTFO
|
||||
if (!Session::exists('interface', $_COOKIE[AmpConfig::get('session_name')]) && !Session::exists('api', $_REQUEST['auth'])) {
|
||||
debug_event('graph', 'Access denied, checked cookie session:' . $_COOKIE[AmpConfig::get('session_name')] . ' and auth:' . $_REQUEST['auth'], 1);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!AmpConfig::get('statistical_graphs')) {
|
||||
debug_event('graph', 'Access denied, statistical graph disabled.', 1);
|
||||
exit;
|
||||
}
|
||||
|
||||
$type = $_REQUEST['type'];
|
||||
|
||||
$user_id = intval($_REQUEST['user_id']);
|
||||
$object_type = (string) scrub_in($_REQUEST['object_type']);
|
||||
if (!Core::is_library_item($object_type)) {
|
||||
$object_type = null;
|
||||
}
|
||||
$object_id = intval($_REQUEST['object_id']);
|
||||
$start_date = scrub_in($_REQUEST['start_date']);
|
||||
$end_date = scrub_in($_REQUEST['end_date']);
|
||||
$zoom = (string) scrub_in($_REQUEST['zoom']);
|
||||
|
||||
$width = intval($_REQUEST['width']);
|
||||
$height = intval($_REQUEST['height']);
|
||||
|
||||
$graph = new Graph();
|
||||
|
||||
switch ($type) {
|
||||
case 'user_hits':
|
||||
$graph->render_user_hits($user_id, $object_type, $object_id, $start_date, $end_date, $zoom, $width, $height);
|
||||
break;
|
||||
case 'user_bandwidth':
|
||||
$graph->render_user_bandwidth($user_id, $object_type, $object_id, $start_date, $end_date, $zoom, $width, $height);
|
||||
break;
|
||||
case 'catalog_files':
|
||||
$graph->render_catalog_files($user_id, $object_type, $object_id, $start_date, $end_date, $zoom, $width, $height);
|
||||
break;
|
||||
case 'catalog_size':
|
||||
$graph->render_catalog_size($user_id, $object_type, $object_id, $start_date, $end_date, $zoom, $width, $height);
|
||||
break;
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -32,10 +32,12 @@
|
|||
define('NO_SESSION','1');
|
||||
require_once 'lib/init.php';
|
||||
|
||||
// Check to see if they've got an interface session or a valid API session, if not GTFO
|
||||
if (!Session::exists('interface', $_COOKIE[AmpConfig::get('session_name')]) && !Session::exists('api', $_REQUEST['auth'])) {
|
||||
debug_event('image','Access denied, checked cookie session:' . $_COOKIE[AmpConfig::get('session_name')] . ' and auth:' . $_REQUEST['auth'], 1);
|
||||
exit;
|
||||
if (AmpConfig::get('use_auth') && AmpConfig::get('require_session')) {
|
||||
// Check to see if they've got an interface session or a valid API session, if not GTFO
|
||||
if (!Session::exists('interface', $_COOKIE[AmpConfig::get('session_name')]) && !Session::exists('api', $_REQUEST['auth'])) {
|
||||
debug_event('image','Access denied, checked cookie session:' . $_COOKIE[AmpConfig::get('session_name')] . ' and auth:' . $_REQUEST['auth'], 1);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// If we aren't resizing just trash thumb
|
||||
|
@ -46,44 +48,18 @@ if (!isset($_GET['object_type'])) {
|
|||
$_GET['object_type'] = 'album';
|
||||
}
|
||||
|
||||
$type = Art::validate_type($_GET['object_type']);
|
||||
$type = $_GET['object_type'];
|
||||
if (!Core::is_library_item($type))
|
||||
exit;
|
||||
|
||||
/* Decide what size this image is */
|
||||
switch ($_GET['thumb']) {
|
||||
case '1':
|
||||
/* This is used by the now_playing stuff */
|
||||
$size['height'] = '75';
|
||||
$size['width'] = '75';
|
||||
break;
|
||||
case '2':
|
||||
$size['height'] = '128';
|
||||
$size['width'] = '128';
|
||||
break;
|
||||
case '3':
|
||||
/* This is used by the flash player */
|
||||
$size['height'] = '80';
|
||||
$size['width'] = '80';
|
||||
break;
|
||||
case '4':
|
||||
/* Web Player size */
|
||||
$size['height'] = 200;
|
||||
$size['width'] = 200; // 200px width, set via CSS
|
||||
break;
|
||||
case '5':
|
||||
/* Web Player size */
|
||||
$size['height'] = 32;
|
||||
$size['width'] = 32;
|
||||
break;
|
||||
default:
|
||||
$size['height'] = '275';
|
||||
$size['width'] = '275';
|
||||
if (!isset($_GET['thumb'])) { $return_raw = true; }
|
||||
break;
|
||||
} // define size based on thumbnail
|
||||
$size = Art::get_thumb_size($_GET['thumb']);
|
||||
$kind = isset($_GET['kind']) ? $_GET['kind'] : 'default';
|
||||
|
||||
$image = '';
|
||||
$mime = '';
|
||||
$filename = '';
|
||||
$etag = '';
|
||||
$typeManaged = false;
|
||||
if (isset($_GET['type'])) {
|
||||
switch ($_GET['type']) {
|
||||
|
@ -102,20 +78,47 @@ if (isset($_GET['type'])) {
|
|||
}
|
||||
}
|
||||
if (!$typeManaged) {
|
||||
$media = new $type($_GET['id']);
|
||||
$filename = $media->name;
|
||||
$item = new $type($_GET['object_id']);
|
||||
$filename = $item->name ?: $item->title;
|
||||
|
||||
$art = new Art($media->id,$type);
|
||||
$art = new Art($item->id, $type, $kind);
|
||||
$art->get_db();
|
||||
$etag = $art->id;
|
||||
|
||||
// That means the client has a cached version of the image
|
||||
$reqheaders = getallheaders();
|
||||
if (isset($reqheaders['If-Modified-Since']) && isset($reqheaders['If-None-Match'])) {
|
||||
$ccontrol = $reqheaders['Cache-Control'];
|
||||
if ($ccontrol != 'no-cache') {
|
||||
$cetagf = explode('-', $reqheaders['If-None-Match']);
|
||||
$cetag = $cetagf[0];
|
||||
// Same image than the cached one? Use the cache.
|
||||
if ($cetag == $etag) {
|
||||
header('HTTP/1.1 304 Not Modified');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$art->raw_mime) {
|
||||
$mime = 'image/jpeg';
|
||||
$image = file_get_contents(AmpConfig::get('prefix') .
|
||||
AmpConfig::get('theme_path') .
|
||||
'/images/blankalbum.jpg');
|
||||
$defaultimg = AmpConfig::get('prefix') . AmpConfig::get('theme_path') . '/images/';
|
||||
switch ($type) {
|
||||
case 'video':
|
||||
case 'tvshow':
|
||||
case 'tvshow_season':
|
||||
$mime = 'image/png';
|
||||
$defaultimg .= "blankmovie.png";
|
||||
break;
|
||||
default:
|
||||
$mime = 'image/jpeg';
|
||||
$defaultimg .= "blankalbum.jpg";
|
||||
break;
|
||||
}
|
||||
$image = file_get_contents($defaultimg);
|
||||
} else {
|
||||
if ($_GET['thumb']) {
|
||||
$thumb_data = $art->get_thumb($size);
|
||||
$etag .= '-' . $_GET['thumb'];
|
||||
}
|
||||
|
||||
$mime = isset($thumb_data['thumb_mime']) ? $thumb_data['thumb_mime'] : $art->raw_mime;
|
||||
|
@ -129,7 +132,11 @@ if (!empty($image)) {
|
|||
|
||||
// Send the headers and output the image
|
||||
$browser = new Horde_Browser();
|
||||
header('Expires: '.gmdate('D, d M Y H:i:s \G\M\T', time() + 604800));
|
||||
if (!empty($etag)) {
|
||||
header('ETag: ' . $etag);
|
||||
header('Cache-Control: private');
|
||||
header('Last-Modified: '.gmdate('D, d M Y H:i:s \G\M\T', time()));
|
||||
}
|
||||
$browser->downloadHeaders($filename, $mime, true);
|
||||
echo $image;
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
BIN
sources/images/fileupload-border.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
sources/images/fileupload-icons.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
sources/images/icon_clean.png
Normal file
After Width: | Height: | Size: 859 B |
BIN
sources/images/icon_file_refresh.png
Normal file
After Width: | Height: | Size: 990 B |
Before Width: | Height: | Size: 635 B After Width: | Height: | Size: 593 B |
BIN
sources/images/icon_play_next.png
Normal file
After Width: | Height: | Size: 635 B |
BIN
sources/images/icon_replaygain.png
Normal file
After Width: | Height: | Size: 144 B |
BIN
sources/images/icon_share_facebook.png
Normal file
After Width: | Height: | Size: 573 B |
BIN
sources/images/icon_share_googleplus.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
sources/images/icon_share_twitter.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
sources/images/icon_sort.png
Normal file
After Width: | Height: | Size: 577 B |
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -22,12 +22,6 @@
|
|||
|
||||
require_once 'lib/init.php';
|
||||
|
||||
if (AmpConfig::get('iframes')) {
|
||||
if (!isset($_GET['framed'])) {
|
||||
UI::show_mainframes();
|
||||
exit;
|
||||
}
|
||||
}
|
||||
UI::show_header();
|
||||
|
||||
$action = isset($_REQUEST['action']) ? scrub_in($_REQUEST['action']) : null;
|
||||
|
@ -42,7 +36,7 @@ $_SESSION['catalog'] = 0;
|
|||
* refresh_javascript include. Must be greater then 5, I'm not
|
||||
* going to let them break their servers
|
||||
*/
|
||||
if (AmpConfig::get('refresh_limit') > 5) {
|
||||
if (AmpConfig::get('refresh_limit') > 5 && AmpConfig::get('home_now_playing')) {
|
||||
$refresh_limit = AmpConfig::get('refresh_limit');
|
||||
$ajax_url = '?page=index&action=reloadnp';
|
||||
require_once AmpConfig::get('prefix') . '/templates/javascript_refresh.inc.php';
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -37,6 +37,7 @@ define('INSTALL', 1);
|
|||
|
||||
$htaccess_play_file = AmpConfig::get('prefix') . '/play/.htaccess';
|
||||
$htaccess_rest_file = AmpConfig::get('prefix') . '/rest/.htaccess';
|
||||
$htaccess_channel_file = AmpConfig::get('prefix') . '/channel/.htaccess';
|
||||
|
||||
// Clean up incoming variables
|
||||
$web_path = scrub_in($_REQUEST['web_path']);
|
||||
|
@ -65,6 +66,20 @@ if (isset($_REQUEST['transcode_template'])) {
|
|||
install_config_transcode_mode($mode);
|
||||
}
|
||||
|
||||
if (isset($_REQUEST['usecase'])) {
|
||||
$case = $_REQUEST['usecase'];
|
||||
if (Dba::check_database()) {
|
||||
install_config_use_case($case);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_REQUEST['backends'])) {
|
||||
$backends = $_REQUEST['backends'];
|
||||
if (Dba::check_database()) {
|
||||
install_config_backends($backends);
|
||||
}
|
||||
}
|
||||
|
||||
// Charset and gettext setup
|
||||
$htmllang = $_REQUEST['htmllang'];
|
||||
$charset = $_REQUEST['charset'];
|
||||
|
@ -89,7 +104,7 @@ load_gettext();
|
|||
header ('Content-Type: text/html; charset=' . AmpConfig::get('site_charset'));
|
||||
|
||||
// Correct potential \ or / in the dirname
|
||||
$safe_dirname = rtrim(dirname($_SERVER['PHP_SELF']),"/\\");
|
||||
$safe_dirname = get_web_path();
|
||||
|
||||
$web_path = $http_type . $_SERVER['HTTP_HOST'] . $safe_dirname;
|
||||
|
||||
|
@ -119,29 +134,54 @@ switch ($_REQUEST['action']) {
|
|||
|
||||
// Now that it's inserted save the lang preference
|
||||
Preference::update('lang', '-1', AmpConfig::get('lang'));
|
||||
|
||||
header ('Location: ' . $web_path . "/install.php?action=show_create_config&local_db=$database&local_host=$hostname&local_port=$port&htmllang=$htmllang&charset=$charset");
|
||||
break;
|
||||
case 'create_config':
|
||||
$download = (!isset($_POST['write']));
|
||||
$download_htaccess_rest = (isset($_POST['download_htaccess_rest']));
|
||||
$download_htaccess_play = (isset($_POST['download_htaccess_play']));
|
||||
$write_htaccess_rest = (isset($_POST['write_htaccess_rest']));
|
||||
$write_htaccess_play = (isset($_POST['write_htaccess_play']));
|
||||
|
||||
if ($write_htaccess_rest || $download_htaccess_rest) {
|
||||
$created_config = install_rewrite_rules($htaccess_rest_file, $_POST['web_path'], $download_htaccess_rest);
|
||||
} elseif ($write_htaccess_play || $download_htaccess_play) {
|
||||
$created_config = install_rewrite_rules($htaccess_play_file, $_POST['web_path'], $download_htaccess_play);
|
||||
} else {
|
||||
$created_config = install_create_config($download);
|
||||
}
|
||||
|
||||
require_once 'templates/show_install_config.inc.php';
|
||||
break;
|
||||
case 'show_create_config':
|
||||
require_once 'templates/show_install_config.inc.php';
|
||||
break;
|
||||
case 'create_config':
|
||||
$all = (isset($_POST['create_all']));
|
||||
$skip = (isset($_POST['skip_config']));
|
||||
if (!$skip) {
|
||||
$write = (isset($_POST['write']));
|
||||
$download = (isset($_POST['download']));
|
||||
$download_htaccess_channel = (isset($_POST['download_htaccess_channel']));
|
||||
$download_htaccess_rest = (isset($_POST['download_htaccess_rest']));
|
||||
$download_htaccess_play = (isset($_POST['download_htaccess_play']));
|
||||
$write_htaccess_channel = (isset($_POST['write_htaccess_channel']));
|
||||
$write_htaccess_rest = (isset($_POST['write_htaccess_rest']));
|
||||
$write_htaccess_play = (isset($_POST['write_htaccess_play']));
|
||||
|
||||
$created_config = true;
|
||||
if ($write_htaccess_channel || $download_htaccess_channel || $all) {
|
||||
$created_config = $created_config && install_rewrite_rules($htaccess_channel_file, $_POST['web_path'], $download_htaccess_channel);
|
||||
}
|
||||
if ($write_htaccess_rest || $download_htaccess_rest || $all) {
|
||||
$created_config = $created_config && install_rewrite_rules($htaccess_rest_file, $_POST['web_path'], $download_htaccess_rest);
|
||||
}
|
||||
if ($write_htaccess_play || $download_htaccess_play || $all) {
|
||||
$created_config = $created_config && install_rewrite_rules($htaccess_play_file, $_POST['web_path'], $download_htaccess_play);
|
||||
}
|
||||
if ($write || $download || $all) {
|
||||
$created_config = $created_config && install_create_config($download);
|
||||
}
|
||||
}
|
||||
case 'show_create_account':
|
||||
$results = parse_ini_file($configfile);
|
||||
if (!isset($created_config)) $created_config = true;
|
||||
|
||||
/* Make sure we've got a valid config file */
|
||||
if (!check_config_values($results) || !$created_config) {
|
||||
Error::add('general', T_('Error: Config files not found or unreadable'));
|
||||
require_once AmpConfig::get('prefix') . '/templates/show_install_config.inc.php';
|
||||
break;
|
||||
}
|
||||
|
||||
// Don't try to add administrator user on existing database
|
||||
if (install_check_status($configfile)) {
|
||||
require_once AmpConfig::get('prefix') . '/templates/show_install_account.inc.php';
|
||||
} else {
|
||||
header ("Location: " . $web_path . '/login.php');
|
||||
}
|
||||
break;
|
||||
case 'create_account':
|
||||
$results = parse_ini_file($configfile);
|
||||
AmpConfig::set_by_array($results, true);
|
||||
|
@ -153,19 +193,13 @@ switch ($_REQUEST['action']) {
|
|||
break;
|
||||
}
|
||||
|
||||
header ("Location: " . $web_path . '/login.php');
|
||||
break;
|
||||
case 'show_create_account':
|
||||
$results = parse_ini_file($configfile);
|
||||
// Automatically log-in the newly created user
|
||||
Session::create_cookie();
|
||||
Session::create(array('type' => 'mysql', 'username' => $username));
|
||||
$_SESSION['userdata']['username'] = $username;
|
||||
Session::check();
|
||||
|
||||
/* Make sure we've got a valid config file */
|
||||
if (!check_config_values($results)) {
|
||||
Error::add('general', T_('Error: Config file not found or unreadable'));
|
||||
require_once AmpConfig::get('prefix') . '/templates/show_install_config.inc.php';
|
||||
break;
|
||||
}
|
||||
|
||||
require_once AmpConfig::get('prefix') . '/templates/show_install_account.inc.php';
|
||||
header ("Location: " . $web_path . '/index.php');
|
||||
break;
|
||||
case 'init':
|
||||
require_once 'templates/show_install.inc.php';
|
||||
|
|
111
sources/labels.php
Normal file
|
@ -0,0 +1,111 @@
|
|||
<?php
|
||||
/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
|
||||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
require_once 'lib/init.php';
|
||||
|
||||
UI::show_header();
|
||||
|
||||
// Switch on the incomming action
|
||||
switch ($_REQUEST['action']) {
|
||||
case 'delete':
|
||||
if (AmpConfig::get('demo_mode')) { break; }
|
||||
|
||||
$label_id = scrub_in($_REQUEST['label_id']);
|
||||
show_confirmation(
|
||||
T_('Label Deletion'),
|
||||
T_('Are you sure you want to permanently delete this label?'),
|
||||
AmpConfig::get('web_path')."/labels.php?action=confirm_delete&label_id=" . $label_id,
|
||||
1,
|
||||
'delete_label'
|
||||
);
|
||||
break;
|
||||
case 'confirm_delete':
|
||||
if (AmpConfig::get('demo_mode')) { break; }
|
||||
|
||||
$label = new Label($_REQUEST['label_id']);
|
||||
if (!Catalog::can_remove($label)) {
|
||||
debug_event('label', 'Unauthorized to remove the label `.' . $label->id . '`.', 1);
|
||||
UI::access_denied();
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($label->remove()) {
|
||||
show_confirmation(T_('Label Deletion'), T_('Label has been deleted.'), AmpConfig::get('web_path'));
|
||||
} else {
|
||||
show_confirmation(T_('Label Deletion'), T_('Cannot delete this label.'), AmpConfig::get('web_path'));
|
||||
}
|
||||
break;
|
||||
case 'add_label':
|
||||
// Must be at least a content manager or edit upload enabled
|
||||
if (!Access::check('interface','50') && !AmpConfig::get('upload_allow_edit')) {
|
||||
UI::access_denied();
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!Core::form_verify('add_label','post')) {
|
||||
UI::access_denied();
|
||||
exit;
|
||||
}
|
||||
|
||||
// Remove unauthorized defined values from here
|
||||
if (isset($_POST['user'])) {
|
||||
unset($_POST['user']);
|
||||
}
|
||||
if (isset($_POST['creation_date'])) {
|
||||
unset($_POST['creation_date']);
|
||||
}
|
||||
|
||||
$label_id = Label::create($_POST);
|
||||
if (!$label_id) {
|
||||
require_once AmpConfig::get('prefix') . '/templates/show_add_label.inc.php';
|
||||
} else {
|
||||
$body = T_('Label Added');
|
||||
$title = '';
|
||||
show_confirmation($title, $body, AmpConfig::get('web_path') . '/browse.php?action=label');
|
||||
}
|
||||
break;
|
||||
case 'show':
|
||||
$label_id = intval($_REQUEST['label']);
|
||||
if (!$label_id) {
|
||||
if (!empty($_REQUEST['name'])) {
|
||||
$label_id = Label::lookup($_REQUEST);
|
||||
}
|
||||
}
|
||||
if ($label_id > 0) {
|
||||
$label = new Label($label_id);
|
||||
$label->format();
|
||||
$object_ids = $label->get_artists();
|
||||
$object_type = 'artist';
|
||||
require_once AmpConfig::get('prefix') . '/templates/show_label.inc.php';
|
||||
UI::show_footer();
|
||||
exit;
|
||||
}
|
||||
case 'show_add_label':
|
||||
if (Access::check('interface','50') || AmpConfig::get('upload_allow_edit')) {
|
||||
require_once AmpConfig::get('prefix') . '/templates/show_add_label.inc.php';
|
||||
} else {
|
||||
echo T_('Label cannot be found.');
|
||||
}
|
||||
break;
|
||||
} // end switch
|
||||
|
||||
UI::show_footer();
|
|
@ -1,2 +1,10 @@
|
|||
Order deny,allow
|
||||
Deny from all
|
||||
# Apache 2.4
|
||||
<IfModule mod_authz_core.c>
|
||||
Require all denied
|
||||
</IfModule>
|
||||
|
||||
# Apache 2.2
|
||||
<IfModule mod_access.c>
|
||||
Order deny,allow
|
||||
Deny from all
|
||||
</IfModule>
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -21,93 +21,97 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* get_song_files
|
||||
* get_media_files
|
||||
*
|
||||
* Takes an array of song ids and returns an array of the actual filenames
|
||||
* Takes an array of media ids and returns an array of the actual filenames
|
||||
*
|
||||
* @param array $media_ids Media IDs.
|
||||
*/
|
||||
function get_song_files($media_ids)
|
||||
function get_media_files($media_ids)
|
||||
{
|
||||
$media_files = array();
|
||||
|
||||
$total_size = 0;
|
||||
foreach ($media_ids as $element) {
|
||||
if (is_array($element)) {
|
||||
$type = array_shift($element);
|
||||
$media = new $type(array_shift($element));
|
||||
if (isset($element['object_type'])) {
|
||||
$type = $element['object_type'];
|
||||
$id = $element['object_id'];
|
||||
} else {
|
||||
$type = array_shift($element);
|
||||
$id = array_shift($element);
|
||||
}
|
||||
$media = new $type($id);
|
||||
} else {
|
||||
$media = new Song($element);
|
||||
}
|
||||
if ($media->enabled) {
|
||||
$total_size += sprintf("%.2f",($media->size/1048576));
|
||||
$media->format();
|
||||
$dirname = $media->f_album_full;
|
||||
//debug_event('batch.lib.php', 'Songs file {'.$media->file.'}...', '5');
|
||||
$total_size += sprintf("%.2f",($media->size/1048576));
|
||||
$dirname = '';
|
||||
$parent = $media->get_parent();
|
||||
if ($parent != null) {
|
||||
$pobj = new $parent['object_type']($parent['object_id']);
|
||||
$pobj->format();
|
||||
$dirname = $pobj->get_fullname();
|
||||
}
|
||||
if (!array_key_exists($dirname, $media_files)) {
|
||||
$media_files[$dirname] = array();
|
||||
}
|
||||
array_push($media_files[$dirname], $media->file);
|
||||
array_push($media_files[$dirname], Core::conv_lc_file($media->file));
|
||||
}
|
||||
}
|
||||
|
||||
return array($media_files, $total_size);
|
||||
} //get_song_files
|
||||
} //get_media_files
|
||||
|
||||
/**
|
||||
* send_zip
|
||||
*
|
||||
* takes array of full paths to songs
|
||||
* takes array of full paths to medias
|
||||
* zips them and sends them
|
||||
*
|
||||
* @param string $name name of the zip file to be created
|
||||
* @param array $song_files array of full paths to songs to zip create w/ call to get_song_files
|
||||
* @param array $media_files array of full paths to medias to zip create w/ call to get_media_files
|
||||
*/
|
||||
function send_zip($name, $song_files)
|
||||
function send_zip($name, $media_files)
|
||||
{
|
||||
// Check if they want to save it to a file, if so then make sure they've
|
||||
// got a defined path as well and that it's writable.
|
||||
$basedir = '';
|
||||
if (AmpConfig::get('file_zip_download') && AmpConfig::get('tmp_dir_path')) {
|
||||
// Check writeable
|
||||
if (!is_writable(AmpConfig::get('tmp_dir_path'))) {
|
||||
$in_memory = '1';
|
||||
debug_event('Error','File Zip Path:' . AmpConfig::get('tmp_dir_path') . ' is not writable','1');
|
||||
} else {
|
||||
$in_memory = '0';
|
||||
$basedir = AmpConfig::get('tmp_dir_path');
|
||||
}
|
||||
} else {
|
||||
$in_memory = '1';
|
||||
} // if file downloads
|
||||
|
||||
/* Require needed library */
|
||||
require_once AmpConfig::get('prefix') . '/modules/archive/archive.lib.php';
|
||||
$arc = new zip_file($name . ".zip" );
|
||||
require_once AmpConfig::get('prefix') . '/modules/ZipStream/ZipStream.php';
|
||||
$arc = new ZipStream\ZipStream($name . ".zip" );
|
||||
$options = array(
|
||||
'inmemory' => $in_memory, // create archive in memory
|
||||
'basedir' => $basedir,
|
||||
'storepaths' => 0, // only store file name, not full path
|
||||
'level' => 0, // no compression
|
||||
'comment' => AmpConfig::get('file_zip_comment'),
|
||||
'type' => "zip"
|
||||
);
|
||||
|
||||
$arc->set_options( $options );
|
||||
foreach ($song_files as $dir => $files) {
|
||||
$arc->add_files($files, $dir);
|
||||
foreach ($media_files as $dir => $files) {
|
||||
foreach ($files as $file) {
|
||||
$arc->addFileFromPath($dir . "/" . basename($file), $file, $options);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($arc->error)) {
|
||||
debug_event('archive',"Error: unable to add songs",'3');
|
||||
return false;
|
||||
} // if failed to add songs
|
||||
|
||||
if (!$arc->create_archive()) {
|
||||
debug_event('archive',"Error: unable to create archive",'3');
|
||||
return false;
|
||||
} // if failed to create archive
|
||||
|
||||
$arc->download_file();
|
||||
|
||||
$arc->finish();
|
||||
} // send_zip
|
||||
|
||||
/**
|
||||
* check_can_zip
|
||||
*
|
||||
* Check that an object type is allowed to be zipped.
|
||||
*
|
||||
* @param string $object_type
|
||||
*/
|
||||
function check_can_zip($object_type)
|
||||
{
|
||||
$allowed = true;
|
||||
if (AmpConfig::get('allow_zip_types')) {
|
||||
$allowed = false;
|
||||
$allowed_types = explode(',', AmpConfig::get('allow_zip_types'));
|
||||
foreach ($allowed_types as $atype) {
|
||||
if (trim($atype) == $object_type) {
|
||||
$allowed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $allowed;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -30,27 +30,68 @@
|
|||
class Access
|
||||
{
|
||||
// Variables from DB
|
||||
|
||||
/**
|
||||
* @var int $id
|
||||
*/
|
||||
public $id;
|
||||
/**
|
||||
* @var string $name
|
||||
*/
|
||||
public $name;
|
||||
/**
|
||||
* @var string $start
|
||||
*/
|
||||
public $start;
|
||||
/**
|
||||
* @var string $end
|
||||
*/
|
||||
public $end;
|
||||
/**
|
||||
* @var int $level
|
||||
*/
|
||||
public $level;
|
||||
/**
|
||||
* @var int $user
|
||||
*/
|
||||
public $user;
|
||||
/**
|
||||
* @var string $type
|
||||
*/
|
||||
public $type;
|
||||
/**
|
||||
* @var boolean $enabled
|
||||
*/
|
||||
public $enabled;
|
||||
|
||||
/**
|
||||
* @var string $f_start
|
||||
*/
|
||||
public $f_start;
|
||||
/**
|
||||
* @var string $f_end
|
||||
*/
|
||||
public $f_end;
|
||||
/**
|
||||
* @var string $f_user
|
||||
*/
|
||||
public $f_user;
|
||||
/**
|
||||
* @var string $f_level
|
||||
*/
|
||||
public $f_level;
|
||||
/**
|
||||
* @var string $f_type
|
||||
*/
|
||||
public $f_type;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
*
|
||||
* Takes an ID of the access_id dealie :)
|
||||
* @param int|null $access_id
|
||||
*/
|
||||
public function __construct($access_id = '')
|
||||
public function __construct($access_id = null)
|
||||
{
|
||||
if (!$access_id) { return false; }
|
||||
|
||||
|
@ -69,6 +110,7 @@ class Access
|
|||
* _get_info
|
||||
*
|
||||
* Gets the vars for $this out of the database.
|
||||
* @return array
|
||||
*/
|
||||
private function _get_info()
|
||||
{
|
||||
|
@ -100,6 +142,9 @@ class Access
|
|||
* _verify_range
|
||||
*
|
||||
* This outputs an error if the IP range is bad.
|
||||
* @param string $startp
|
||||
* @param string $endp
|
||||
* @return boolean
|
||||
*/
|
||||
private static function _verify_range($startp, $endp)
|
||||
{
|
||||
|
@ -128,8 +173,10 @@ class Access
|
|||
*
|
||||
* This function takes a named array as a datasource and updates the current
|
||||
* access list entry.
|
||||
* @param array $data
|
||||
* @return boolean
|
||||
*/
|
||||
public function update($data)
|
||||
public function update(array $data)
|
||||
{
|
||||
if (!self::_verify_range($data['start'], $data['end'])) {
|
||||
return false;
|
||||
|
@ -156,8 +203,10 @@ class Access
|
|||
*
|
||||
* This takes a keyed array of data and trys to insert it as a
|
||||
* new ACL entry
|
||||
* @param array $data
|
||||
* @return boolean
|
||||
*/
|
||||
public static function create($data)
|
||||
public static function create(array $data)
|
||||
{
|
||||
if (!self::_verify_range($data['start'], $data['end'])) {
|
||||
return false;
|
||||
|
@ -191,8 +240,10 @@ class Access
|
|||
*
|
||||
* This sees if the ACL that we've specified already exists in order to
|
||||
* prevent duplicates. The name is ignored.
|
||||
* @param array $data
|
||||
* @return boolean
|
||||
*/
|
||||
public static function exists($data)
|
||||
public static function exists(array $data)
|
||||
{
|
||||
$start = inet_pton($data['start']);
|
||||
$end = inet_pton($data['end']);
|
||||
|
@ -214,6 +265,7 @@ class Access
|
|||
* delete
|
||||
*
|
||||
* deletes the specified access_list entry
|
||||
* @param int $id
|
||||
*/
|
||||
public static function delete($id)
|
||||
{
|
||||
|
@ -224,24 +276,26 @@ class Access
|
|||
* check_function
|
||||
*
|
||||
* This checks if specific functionality is enabled.
|
||||
* @param string $type
|
||||
* @return boolean
|
||||
*/
|
||||
public static function check_function($type)
|
||||
{
|
||||
switch ($type) {
|
||||
case 'download':
|
||||
return AmpConfig::get('download');
|
||||
return make_bool(AmpConfig::get('download'));
|
||||
case 'batch_download':
|
||||
if (!function_exists('gzcompress')) {
|
||||
debug_event('access', 'ZLIB extension not loaded, batch download disabled', 3);
|
||||
return false;
|
||||
}
|
||||
if (AmpConfig::get('allow_zip_download') AND $GLOBALS['user']->has_access('25')) {
|
||||
return AmpConfig::get('download');
|
||||
if (AmpConfig::get('allow_zip_download') AND $GLOBALS['user']->has_access('5')) {
|
||||
return make_bool(AmpConfig::get('download'));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -249,6 +303,11 @@ class Access
|
|||
*
|
||||
* This takes a type, ip, user, level and key and then returns whether they
|
||||
* are allowed. The IP is passed as a dotted quad.
|
||||
* @param string $type
|
||||
* @param int|string $user
|
||||
* @param int $level
|
||||
* @param string $ip
|
||||
* @return boolean
|
||||
*/
|
||||
public static function check_network($type, $user, $level, $ip=null)
|
||||
{
|
||||
|
@ -313,8 +372,12 @@ class Access
|
|||
*
|
||||
* Everything uses the global 0,5,25,50,75,100 stuff. GLOBALS['user'] is
|
||||
* always used.
|
||||
* @param string $type
|
||||
* @param int $level
|
||||
* @param int|null $user
|
||||
* @return boolean
|
||||
*/
|
||||
public static function check($type, $level)
|
||||
public static function check($type, $level, $user_id=null)
|
||||
{
|
||||
if (AmpConfig::get('demo_mode')) {
|
||||
return true;
|
||||
|
@ -323,6 +386,10 @@ class Access
|
|||
return true;
|
||||
}
|
||||
|
||||
$user = $GLOBALS['user'];
|
||||
if ($user_id) {
|
||||
$user = new User($user_id);
|
||||
}
|
||||
$level = intval($level);
|
||||
|
||||
// Switch on the type
|
||||
|
@ -330,10 +397,10 @@ class Access
|
|||
case 'localplay':
|
||||
// Check their localplay_level
|
||||
return (AmpConfig::get('localplay_level') >= $level
|
||||
|| $GLOBALS['user']->access >= 100);
|
||||
|| $user->access >= 100);
|
||||
case 'interface':
|
||||
// Check their standard user level
|
||||
return ($GLOBALS['user']->access >= $level);
|
||||
return ($user->access >= $level);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -344,6 +411,8 @@ class Access
|
|||
*
|
||||
* This validates the specified type; it will always return a valid type,
|
||||
* even if you pass in an invalid one.
|
||||
* @param string $type
|
||||
* @return string
|
||||
*/
|
||||
public static function validate_type($type)
|
||||
{
|
||||
|
@ -360,6 +429,7 @@ class Access
|
|||
/**
|
||||
* get_access_lists
|
||||
* returns a full listing of all access rules on this server
|
||||
* @return array
|
||||
*/
|
||||
public static function get_access_lists()
|
||||
{
|
||||
|
@ -380,6 +450,7 @@ class Access
|
|||
* get_level_name
|
||||
*
|
||||
* take the int level and return a named level
|
||||
* @return string
|
||||
*/
|
||||
public function get_level_name()
|
||||
{
|
||||
|
@ -401,6 +472,7 @@ class Access
|
|||
* get_user_name
|
||||
*
|
||||
* Return a name for the users covered by this ACL.
|
||||
* @return string
|
||||
*/
|
||||
public function get_user_name()
|
||||
{
|
||||
|
@ -414,6 +486,7 @@ class Access
|
|||
* get_type_name
|
||||
*
|
||||
* This function returns the pretty name for our current type.
|
||||
* @return string
|
||||
*/
|
||||
public function get_type_name()
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -31,6 +31,7 @@
|
|||
class Ajax
|
||||
{
|
||||
private static $include_override;
|
||||
private static $counter = 0;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
|
@ -46,6 +47,11 @@ class Ajax
|
|||
* observe
|
||||
* This returns a string with the correct and full ajax 'observe' stuff
|
||||
* from jQuery
|
||||
* @param string $source
|
||||
* @param string $method
|
||||
* @param string $action
|
||||
* @param string $confirm
|
||||
* @return string
|
||||
*/
|
||||
public static function observe($source, $method, $action, $confirm='')
|
||||
{
|
||||
|
@ -59,10 +65,15 @@ class Ajax
|
|||
|
||||
$observe = "<script type=\"text/javascript\">";
|
||||
$methodact = (($method == 'click') ? "update_action();" : "");
|
||||
if (!empty($confirm)) {
|
||||
$observe .= "$(".$source_txt.").on('".$method."', function(){ ".$methodact." if (confirm(\"".$confirm."\")) { ".$action." }});";
|
||||
if (AmpConfig::get('ajax_load') && $method == 'load') {
|
||||
$source_txt = "$( document ).ready(";
|
||||
} else {
|
||||
$observe .= "$(".$source_txt.").on('".$method."', function(){ ".$methodact." ".$action.";});";
|
||||
$source_txt = "$(".$source_txt.").on('".$method."', ";
|
||||
}
|
||||
if (!empty($confirm)) {
|
||||
$observe .= $source_txt . "function(){ ".$methodact." if (confirm(\"".$confirm."\")) { ".$action." }});";
|
||||
} else {
|
||||
$observe .= $source_txt . "function(){ ".$methodact." ".$action.";});";
|
||||
}
|
||||
$observe .= "</script>";
|
||||
|
||||
|
@ -73,6 +84,8 @@ class Ajax
|
|||
/**
|
||||
* url
|
||||
* This takes a string and makes an URL
|
||||
* @param string $action
|
||||
* @return string
|
||||
*/
|
||||
public static function url($action)
|
||||
{
|
||||
|
@ -83,6 +96,10 @@ class Ajax
|
|||
* action
|
||||
* This takes the action, the source and the post (if passed) and
|
||||
* generates the full ajax link
|
||||
* @param string $action
|
||||
* @param string $source
|
||||
* @param string $post
|
||||
* @return string
|
||||
*/
|
||||
public static function action($action, $source, $post='')
|
||||
{
|
||||
|
@ -110,6 +127,14 @@ class Ajax
|
|||
* button
|
||||
* This prints out an img of the specified icon with the specified alt
|
||||
* text and then sets up the required ajax for it.
|
||||
* @param string $action
|
||||
* @param string $icon
|
||||
* @param string $alt
|
||||
* @param string $source
|
||||
* @param string $post
|
||||
* @param string $class
|
||||
* @param string $confirm
|
||||
* @return string
|
||||
*/
|
||||
public static function button($action, $icon, $alt, $source='', $post='', $class='', $confirm='')
|
||||
{
|
||||
|
@ -138,24 +163,35 @@ class Ajax
|
|||
* text
|
||||
* This prints out the specified text as a link and sets up the required
|
||||
* ajax for the link so it works correctly
|
||||
* @param string $action
|
||||
* @param string $text
|
||||
* @param string $source
|
||||
* @param string $post
|
||||
* @param string $class
|
||||
* @return string
|
||||
*/
|
||||
public static function text($action, $text, $source, $post='', $class='')
|
||||
{
|
||||
// Avoid duplicate id
|
||||
$source .= '_' . time();
|
||||
// Temporary workaround to avoid sorting on custom base requests
|
||||
if (!defined("NO_BROWSE_SORTING") || strpos($source, "sort_") === false) {
|
||||
// Avoid duplicate id
|
||||
$source .= '_' . time() . '_' . self::$counter++;
|
||||
|
||||
// Format the string we wanna use
|
||||
$ajax_string = self::action($action, $source, $post);
|
||||
// Format the string we wanna use
|
||||
$ajax_string = self::action($action, $source, $post);
|
||||
|
||||
// If they passed a span class
|
||||
if ($class) {
|
||||
$class = ' class="' . $class . '"';
|
||||
// If they passed a span class
|
||||
if ($class) {
|
||||
$class = ' class="' . $class . '"';
|
||||
}
|
||||
|
||||
$string = "<a href=\"javascript:void(0);\" id=\"$source\" $class>$text</a>\n";
|
||||
|
||||
$string .= self::observe($source, 'click', $ajax_string);
|
||||
} else {
|
||||
$string = $text;
|
||||
}
|
||||
|
||||
$string = "<a href=\"javascript:void(0);\" id=\"$source\" $class>$text</a>\n";
|
||||
|
||||
$string .= self::observe($source, 'click', $ajax_string);
|
||||
|
||||
return $string;
|
||||
|
||||
} // text
|
||||
|
@ -163,6 +199,7 @@ class Ajax
|
|||
/**
|
||||
* run
|
||||
* This runs the specified action no questions asked
|
||||
* @param string $action
|
||||
*/
|
||||
public static function run($action)
|
||||
{
|
||||
|
@ -176,6 +213,7 @@ class Ajax
|
|||
* set_include_override
|
||||
* This sets the including div override, used only one place. Kind of a
|
||||
* hack.
|
||||
* @param bool $value
|
||||
*/
|
||||
public static function set_include_override($value)
|
||||
{
|
||||
|
@ -187,6 +225,8 @@ class Ajax
|
|||
* start_container
|
||||
* This checks to see if we're AJAXin'. If we aren't then it echoes out
|
||||
* the html needed to start a container that can be replaced by Ajax.
|
||||
* @param string $name
|
||||
* @param string $class
|
||||
*/
|
||||
public static function start_container($name, $class = '')
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -28,39 +28,153 @@
|
|||
* it is related to the album table in the database.
|
||||
*
|
||||
*/
|
||||
class Album extends database_object
|
||||
class Album extends database_object implements library_item
|
||||
{
|
||||
/* Variables from DB */
|
||||
public $id;
|
||||
public $name;
|
||||
public $disk;
|
||||
public $year;
|
||||
public $prefix;
|
||||
public $mbid; // MusicBrainz ID
|
||||
|
||||
/**
|
||||
* @var int $id
|
||||
*/
|
||||
public $id;
|
||||
/**
|
||||
* @var string $name
|
||||
*/
|
||||
public $name;
|
||||
/**
|
||||
* @var int $album_artist
|
||||
*/
|
||||
public $album_artist;
|
||||
/**
|
||||
* @var int $disk
|
||||
*/
|
||||
public $disk;
|
||||
/**
|
||||
* @var int $year
|
||||
*/
|
||||
public $year;
|
||||
/**
|
||||
* @var string $prefix
|
||||
*/
|
||||
public $prefix;
|
||||
/**
|
||||
* @var string $mbid
|
||||
*/
|
||||
public $mbid; // MusicBrainz ID
|
||||
/**
|
||||
* @var string $mbid_group
|
||||
*/
|
||||
public $mbid_group; // MusicBrainz Release Group ID
|
||||
/**
|
||||
* @var string $release_type
|
||||
*/
|
||||
public $release_type;
|
||||
|
||||
/**
|
||||
* @var int $catalog_id
|
||||
*/
|
||||
public $catalog_id;
|
||||
/**
|
||||
* @var int $song_count
|
||||
*/
|
||||
public $song_count;
|
||||
/**
|
||||
* @var string $artist_prefix
|
||||
*/
|
||||
public $artist_prefix;
|
||||
/**
|
||||
* @var string $artist_name
|
||||
*/
|
||||
public $artist_name;
|
||||
/**
|
||||
* @var int $artist_id
|
||||
*/
|
||||
public $artist_id;
|
||||
/**
|
||||
* @var array $tags
|
||||
*/
|
||||
public $tags;
|
||||
/**
|
||||
* @var string $full_name
|
||||
*/
|
||||
public $full_name; // Prefix + Name, generated
|
||||
/**
|
||||
* @var int $artist_count
|
||||
*/
|
||||
public $artist_count;
|
||||
/**
|
||||
* @var string $f_artist_name
|
||||
*/
|
||||
public $f_artist_name;
|
||||
/**
|
||||
* @var string $f_artist_link
|
||||
*/
|
||||
public $f_artist_link;
|
||||
/**
|
||||
* @var string $f_artist
|
||||
*/
|
||||
public $f_artist;
|
||||
/**
|
||||
* @var string $album_artist_name
|
||||
*/
|
||||
public $album_artist_name;
|
||||
/**
|
||||
* @var string $f_album_artist_name
|
||||
*/
|
||||
public $f_album_artist_name;
|
||||
/**
|
||||
* @var string $f_album_artist_link
|
||||
*/
|
||||
public $f_album_artist_link;
|
||||
/**
|
||||
* @var string $f_name
|
||||
*/
|
||||
public $f_name;
|
||||
public $f_name_link;
|
||||
public $f_link_src;
|
||||
/**
|
||||
* @var string $link
|
||||
*/
|
||||
public $link;
|
||||
/**
|
||||
* @var string $f_link
|
||||
*/
|
||||
public $f_link;
|
||||
/**
|
||||
* @var string $f_tags
|
||||
*/
|
||||
public $f_tags;
|
||||
/**
|
||||
* @var string $f_year
|
||||
*/
|
||||
public $f_year;
|
||||
/**
|
||||
* @var string $f_title
|
||||
*/
|
||||
public $f_title;
|
||||
/**
|
||||
* @var string $f_release_type
|
||||
*/
|
||||
public $f_release_type;
|
||||
|
||||
// cached information
|
||||
/**
|
||||
* @var boolean $_fake
|
||||
*/
|
||||
public $_fake;
|
||||
/**
|
||||
* @var array $_songs
|
||||
*/
|
||||
public $_songs = array();
|
||||
/**
|
||||
* @var array $_mapcache
|
||||
*/
|
||||
private static $_mapcache = array();
|
||||
|
||||
/**
|
||||
* @var array $album_suite
|
||||
*/
|
||||
public $album_suite = array();
|
||||
/**
|
||||
* @var boolean $allow_group_disks
|
||||
*/
|
||||
public $allow_group_disks = false;
|
||||
|
||||
/**
|
||||
|
@ -69,8 +183,9 @@ class Album extends database_object
|
|||
* to this album from the database it does not
|
||||
* pull the album or thumb art by default or
|
||||
* get any of the counts.
|
||||
* @param int|null $id
|
||||
*/
|
||||
public function __construct($id='')
|
||||
public function __construct($id=null)
|
||||
{
|
||||
if (!$id) { return false; }
|
||||
|
||||
|
@ -98,8 +213,10 @@ class Album extends database_object
|
|||
* construct_from_array
|
||||
* This is often used by the metadata class, it fills out an album object from a
|
||||
* named array, _fake is set to true
|
||||
* @param array $data
|
||||
* @return Album
|
||||
*/
|
||||
public static function construct_from_array($data)
|
||||
public static function construct_from_array(array $data)
|
||||
{
|
||||
$album = new Album(0);
|
||||
foreach ($data as $key=>$value) {
|
||||
|
@ -126,8 +243,10 @@ class Album extends database_object
|
|||
* build_cache
|
||||
* This takes an array of object ids and caches all of their information
|
||||
* with a single query
|
||||
* @param array $ids
|
||||
* @return boolean
|
||||
*/
|
||||
public static function build_cache($ids)
|
||||
public static function build_cache(array $ids)
|
||||
{
|
||||
// Nothing to do if they pass us nothing
|
||||
if (!is_array($ids) OR !count($ids)) {
|
||||
|
@ -140,7 +259,7 @@ class Album extends database_object
|
|||
$db_results = Dba::read($sql);
|
||||
|
||||
while ($row = Dba::fetch_assoc($db_results)) {
|
||||
parent::add_to_cache('album',$row['id'],$row);
|
||||
parent::add_to_cache('album', $row['id'], $row);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -151,9 +270,14 @@ class Album extends database_object
|
|||
* _get_extra_info
|
||||
* This pulls the extra information from our tables, this is a 3 table join, which is why we don't normally
|
||||
* do it
|
||||
* @return array
|
||||
*/
|
||||
private function _get_extra_info()
|
||||
private function _get_extra_info($limit_threshold = '')
|
||||
{
|
||||
if (!$this->id) {
|
||||
return array();
|
||||
}
|
||||
|
||||
if (parent::is_cached('album_extra', $this->id)) {
|
||||
return parent::get_from_cache('album_extra', $this->id);
|
||||
}
|
||||
|
@ -203,7 +327,7 @@ class Album extends database_object
|
|||
$results['has_thumb'] = make_bool($art->thumb);
|
||||
|
||||
if (AmpConfig::get('show_played_times')) {
|
||||
$results['object_cnt'] = Stats::get_object_count('album', $this->id);
|
||||
$results['object_cnt'] = Stats::get_object_count('album', $this->id, $limit_threshold);
|
||||
}
|
||||
|
||||
parent::add_to_cache('album_extra', $this->id, $results);
|
||||
|
@ -212,18 +336,55 @@ class Album extends database_object
|
|||
|
||||
} // _get_extra_info
|
||||
|
||||
public function can_edit($user = null)
|
||||
{
|
||||
if (!$user) {
|
||||
$user = $GLOBALS['user']->id;
|
||||
}
|
||||
|
||||
if (!$user)
|
||||
return false;
|
||||
|
||||
if ($this->user !== null && $user == $this->user)
|
||||
return true;
|
||||
|
||||
if (Access::check('interface', 50, $user))
|
||||
return true;
|
||||
|
||||
if (!$this->album_artist)
|
||||
return false;
|
||||
|
||||
if (!AmpConfig::get('upload_allow_edit'))
|
||||
return false;
|
||||
|
||||
$owner = $this->get_user_owner();
|
||||
return ($owner && $owner === $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* check
|
||||
*
|
||||
* Searches for an album; if none is found, insert a new one.
|
||||
* @param string $name
|
||||
* @param int $year
|
||||
* @param int $disk
|
||||
* @param string $mbid
|
||||
* @param string $mbid_group
|
||||
* @param string $album_artist
|
||||
* @param string $release_type
|
||||
* @param boolean $readonly
|
||||
* @return int|null
|
||||
*/
|
||||
public static function check($name, $year = 0, $disk = 0, $mbid = null, $readonly = false)
|
||||
public static function check($name, $year = 0, $disk = 0, $mbid = null, $mbid_group = null, $album_artist = null, $release_type = null, $readonly = false)
|
||||
{
|
||||
if ($mbid == '') $mbid = null;
|
||||
|
||||
$trimmed = Catalog::trim_prefix(trim($name));
|
||||
$name = $trimmed['string'];
|
||||
$prefix = $trimmed['prefix'];
|
||||
$album_artist = intval($album_artist);
|
||||
$album_artist = ($album_artist <= 0) ? null : $album_artist;
|
||||
$mbid = empty($mbid) ? null : $mbid;
|
||||
$mbid_group = empty($mbid_group) ? null : $mbid_group;
|
||||
$release_type = empty($release_type) ? null : $release_type;
|
||||
|
||||
// Not even sure if these can be negative, but better safe than llama.
|
||||
$year = abs(intval($year));
|
||||
|
@ -233,35 +394,36 @@ class Album extends database_object
|
|||
$name = T_('Unknown (Orphaned)');
|
||||
$year = 0;
|
||||
$disk = 0;
|
||||
$album_artist = null;
|
||||
}
|
||||
if (isset(self::$_mapcache[$name][$disk][$mbid][$album_artist])) {
|
||||
return self::$_mapcache[$name][$disk][$mbid][$album_artist];
|
||||
}
|
||||
|
||||
if (isset(self::$_mapcache[$name][$year][$disk][$mbid])) {
|
||||
return self::$_mapcache[$name][$year][$disk][$mbid];
|
||||
}
|
||||
|
||||
$sql = 'SELECT `id` FROM `album` WHERE `name` = ? AND `disk` = ? AND `year` = ? AND `mbid` ';
|
||||
$params = array($name, $disk, $year);
|
||||
$sql = 'SELECT `album`.`id` FROM `album` WHERE `album`.`name` = ? AND `album`.`disk` = ? ';
|
||||
$params = array($name, $disk);
|
||||
|
||||
if ($mbid) {
|
||||
$sql .= '= ? ';
|
||||
$sql .= 'AND `album`.`mbid` = ? ';
|
||||
$params[] = $mbid;
|
||||
} else {
|
||||
$sql .= 'IS NULL ';
|
||||
$sql .= 'AND `album`.`mbid` IS NULL ';
|
||||
}
|
||||
if ($prefix) {
|
||||
$sql .= 'AND `album`.`prefix` = ? ';
|
||||
$params[] = $prefix;
|
||||
}
|
||||
|
||||
$sql .= 'AND `prefix` ';
|
||||
if ($prefix) {
|
||||
$sql .= '= ?';
|
||||
$params[] = $prefix;
|
||||
} else {
|
||||
$sql .= 'IS NULL';
|
||||
if ($album_artist) {
|
||||
$sql .= 'AND `album`.`album_artist` = ? ';
|
||||
$params[] = $album_artist;
|
||||
}
|
||||
|
||||
$db_results = Dba::read($sql, $params);
|
||||
|
||||
if ($row = Dba::fetch_assoc($db_results)) {
|
||||
$id = $row['id'];
|
||||
self::$_mapcache[$name][$year][$disk][$mbid] = $id;
|
||||
self::$_mapcache[$name][$disk][$mbid][$album_artist] = $id;
|
||||
return $id;
|
||||
}
|
||||
|
||||
|
@ -269,9 +431,9 @@ class Album extends database_object
|
|||
return null;
|
||||
}
|
||||
|
||||
$sql = 'INSERT INTO `album` (`name`, `prefix`, `year`, `disk`, `mbid`) VALUES (?, ?, ?, ?, ?)';
|
||||
$sql = 'INSERT INTO `album` (`name`, `prefix`, `year`, `disk`, `mbid`, `mbid_group`, `release_type`, `album_artist`) VALUES (?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
|
||||
$db_results = Dba::write($sql, array($name, $prefix, $year, $disk, $mbid));
|
||||
$db_results = Dba::write($sql, array($name, $prefix, $year, $disk, $mbid, $mbid_group, $release_type, $album_artist));
|
||||
if (!$db_results) {
|
||||
return null;
|
||||
}
|
||||
|
@ -287,7 +449,7 @@ class Album extends database_object
|
|||
}
|
||||
}
|
||||
|
||||
self::$_mapcache[$name][$year][$disk][$mbid] = $id;
|
||||
self::$_mapcache[$name][$disk][$mbid][$album_artist] = $id;
|
||||
return $id;
|
||||
}
|
||||
|
||||
|
@ -296,6 +458,9 @@ class Album extends database_object
|
|||
* gets the songs for this album takes an optional limit
|
||||
* and an optional artist, if artist is passed it only gets
|
||||
* songs with this album + specified artist
|
||||
* @param int $limit
|
||||
* @param string $artist
|
||||
* @return int[]
|
||||
*/
|
||||
public function get_songs($limit = 0,$artist='')
|
||||
{
|
||||
|
@ -331,6 +496,8 @@ class Album extends database_object
|
|||
/**
|
||||
* get_http_album_query_ids
|
||||
* return the html album parameters with all album suite ids
|
||||
* @param string $url_param_name
|
||||
* @return string
|
||||
*/
|
||||
public function get_http_album_query_ids($url_param_name)
|
||||
{
|
||||
|
@ -346,6 +513,7 @@ class Album extends database_object
|
|||
/**
|
||||
* get_group_disks_ids
|
||||
* return all album suite ids or current album if no albums
|
||||
* @return int[]
|
||||
*/
|
||||
public function get_group_disks_ids()
|
||||
{
|
||||
|
@ -360,14 +528,16 @@ class Album extends database_object
|
|||
/**
|
||||
* get_album_suite
|
||||
* gets the album ids with the same musicbrainz identifier
|
||||
* @param int $catalog
|
||||
* return int[]
|
||||
*/
|
||||
public function get_album_suite($catalog = '')
|
||||
public function get_album_suite($catalog = 0)
|
||||
{
|
||||
$results = array();
|
||||
|
||||
$catalog_where = "";
|
||||
$catalog_join = "LEFT JOIN `catalog` ON `catalog`.`id` = `song`.`catalog`";
|
||||
if (!empty($catalog)) {
|
||||
if ($catalog) {
|
||||
$catalog_where .= " AND `catalog`.`id` = '$catalog'";
|
||||
}
|
||||
if (AmpConfig::get('catalog_disable')) {
|
||||
|
@ -390,6 +560,8 @@ class Album extends database_object
|
|||
/**
|
||||
* has_track
|
||||
* This checks to see if this album has a track of the specified title
|
||||
* @param string $title
|
||||
* @return array
|
||||
*/
|
||||
public function has_track($title)
|
||||
{
|
||||
|
@ -402,39 +574,69 @@ class Album extends database_object
|
|||
|
||||
} // has_track
|
||||
|
||||
/**
|
||||
* get_addtime_first_song
|
||||
* Get the add date of first added song.
|
||||
* @return int
|
||||
*/
|
||||
public function get_addtime_first_song()
|
||||
{
|
||||
$time = 0;
|
||||
|
||||
$sql = "SELECT MIN(`addition_time`) FROM `song` WHERE `album` = ?";
|
||||
$db_results = Dba::read($sql, array($this->id));
|
||||
if ($data = Dba::fetch_row($db_results)) {
|
||||
$time = $data[0];
|
||||
}
|
||||
|
||||
return $time;
|
||||
}
|
||||
|
||||
/**
|
||||
* format
|
||||
* This is the format function for this object. It sets cleaned up
|
||||
* album information with the base required
|
||||
* f_link, f_name
|
||||
*/
|
||||
public function format()
|
||||
public function format($details = true, $limit_threshold = '')
|
||||
{
|
||||
$web_path = AmpConfig::get('web_path');
|
||||
|
||||
/* Pull the advanced information */
|
||||
$data = $this->_get_extra_info();
|
||||
foreach ($data as $key=>$value) { $this->$key = $value; }
|
||||
if ($details) {
|
||||
/* Pull the advanced information */
|
||||
$data = $this->_get_extra_info($limit_threshold);
|
||||
foreach ($data as $key=>$value) { $this->$key = $value; }
|
||||
|
||||
if ($this->album_artist) {
|
||||
$Album_artist = new Artist($this->album_artist);
|
||||
$Album_artist->format();
|
||||
$this->album_artist_name = $Album_artist->name;
|
||||
$this->f_album_artist_name = $Album_artist->f_name;
|
||||
$this->f_album_artist_link = "<a href=\"" . $web_path . "/artists.php?action=show&artist=" . $this->album_artist . "\" title=\"" . scrub_out($this->album_artist_name) . "\">" . $this->f_album_artist_name . "</a>";
|
||||
}
|
||||
|
||||
$this->tags = Tag::get_top_tags('album', $this->id);
|
||||
$this->f_tags = Tag::get_display($this->tags, true, 'album');
|
||||
}
|
||||
|
||||
/* Truncate the string if it's to long */
|
||||
$this->f_name = $this->full_name;
|
||||
|
||||
$this->f_link_src = $web_path . '/albums.php?action=show&album=' . scrub_out($this->id);
|
||||
$this->f_name_link = "<a href=\"" . $this->f_link_src . "\" title=\"" . scrub_out($this->full_name) . "\">" . scrub_out($this->f_name);
|
||||
$this->link = $web_path . '/albums.php?action=show&album=' . scrub_out($this->id);
|
||||
$this->f_link = "<a href=\"" . $this->link . "\" title=\"" . scrub_out($this->full_name) . "\">" . scrub_out($this->f_name);
|
||||
|
||||
// Looking if we need to combine or display disks
|
||||
if ($this->disk && (!$this->allow_group_disks || ($this->allow_group_disks && !AmpConfig::get('album_group')))) {
|
||||
$this->f_name_link .= " <span class=\"discnb\">[" . T_('Disk') . " " . $this->disk . "]</span>";
|
||||
$this->f_link .= " <span class=\"discnb\">[" . T_('Disk') . " " . $this->disk . "]</span>";
|
||||
}
|
||||
|
||||
$this->f_name_link .="</a>";
|
||||
$this->f_link .="</a>";
|
||||
|
||||
$this->f_link = $this->f_name_link;
|
||||
$this->f_title = $this->full_name;
|
||||
if ($this->artist_count == '1') {
|
||||
$artist = trim(trim($this->artist_prefix) . ' ' . trim($this->artist_name));
|
||||
$this->f_artist_name = $artist;
|
||||
$this->f_artist_link = "<a href=\"$web_path/artists.php?action=show&artist=" . $this->artist_id . "\" title=\"" . scrub_out($this->artist_name) . "\">" . $artist . "</a>";
|
||||
$this->f_artist_link = "<a href=\"$web_path/artists.php?action=show&artist=" . $this->artist_id . "\" title=\"" . scrub_out($this->artist_name) . "\">" . $artist . "</a>";
|
||||
$this->f_artist = $artist;
|
||||
} else {
|
||||
$this->f_artist_link = "<span title=\"$this->artist_count " . T_('Artists') . "\">" . T_('Various') . "</span>";
|
||||
|
@ -442,18 +644,180 @@ class Album extends database_object
|
|||
$this->f_artist_name = $this->f_artist;
|
||||
}
|
||||
|
||||
if ($this->year == '0') {
|
||||
$this->year = "N/A";
|
||||
if (!$this->year) {
|
||||
$this->f_year = "N/A";
|
||||
}
|
||||
|
||||
$this->tags = Tag::get_top_tags('album', $this->id);
|
||||
$this->f_tags = Tag::get_display($this->tags);
|
||||
$this->f_release_type = ucwords($this->release_type);
|
||||
|
||||
} // format
|
||||
|
||||
/**
|
||||
* Get item keywords for metadata searches.
|
||||
* @return array
|
||||
*/
|
||||
public function get_keywords()
|
||||
{
|
||||
$keywords = array();
|
||||
$keywords['mb_albumid'] = array('important' => false,
|
||||
'label' => T_('Album MusicBrainzID'),
|
||||
'value' => $this->mbid);
|
||||
$keywords['mb_albumid_group'] = array('important' => false,
|
||||
'label' => T_('Release Group MusicBrainzID'),
|
||||
'value' => $this->mbid_group);
|
||||
$keywords['artist'] = array('important' => true,
|
||||
'label' => T_('Artist'),
|
||||
'value' => (($this->artist_count < 2) ? $this->f_artist_name : ''));
|
||||
$keywords['album'] = array('important' => true,
|
||||
'label' => T_('Album'),
|
||||
'value' => $this->f_name);
|
||||
|
||||
return $keywords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get item fullname.
|
||||
* @return string
|
||||
*/
|
||||
public function get_fullname()
|
||||
{
|
||||
return $this->f_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parent item description.
|
||||
* @return array|null
|
||||
*/
|
||||
public function get_parent()
|
||||
{
|
||||
if ($this->artist_count == 1) {
|
||||
return array('object_type' => 'artist', 'object_id' => $this->artist_id);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get item childrens.
|
||||
* @return array
|
||||
*/
|
||||
public function get_childrens()
|
||||
{
|
||||
return $this->get_medias();
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for item childrens.
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
public function search_childrens($name)
|
||||
{
|
||||
$search['type'] = "song";
|
||||
$search['rule_0_input'] = $name;
|
||||
$search['rule_0_operator'] = 4;
|
||||
$search['rule_0'] = "title";
|
||||
$search['rule_1_input'] = $this->name;
|
||||
$search['rule_1_operator'] = 4;
|
||||
$search['rule_1'] = "album";
|
||||
$search['rule_2_input'] = $this->album_artist_name;
|
||||
$search['rule_2_operator'] = 4;
|
||||
$search['rule_2'] = "artist";
|
||||
$songs = Search::run($search);
|
||||
|
||||
$childrens = array();
|
||||
foreach ($songs as $song) {
|
||||
$childrens[] = array(
|
||||
'object_type' => 'song',
|
||||
'object_id' => $song
|
||||
);
|
||||
}
|
||||
|
||||
return $childrens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all childrens and sub-childrens medias.
|
||||
* @param string $filter_type
|
||||
* @return array
|
||||
*/
|
||||
public function get_medias($filter_type = null)
|
||||
{
|
||||
$medias = array();
|
||||
if (!$filter_type || $filter_type == 'song') {
|
||||
$songs = $this->get_songs();
|
||||
foreach ($songs as $song_id) {
|
||||
$medias[] = array(
|
||||
'object_type' => 'song',
|
||||
'object_id' => $song_id
|
||||
);
|
||||
}
|
||||
}
|
||||
return $medias;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_catalogs
|
||||
*
|
||||
* Get all catalog ids related to this item.
|
||||
* @return int[]
|
||||
*/
|
||||
public function get_catalogs()
|
||||
{
|
||||
return array($this->catalog_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get item's owner.
|
||||
* @return int|null
|
||||
*/
|
||||
public function get_user_owner()
|
||||
{
|
||||
if (!$this->album_artist)
|
||||
return null;
|
||||
|
||||
$artist = new Artist($this->album_artist);
|
||||
return $artist->get_user_owner();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default art kind for this item.
|
||||
* @return string
|
||||
*/
|
||||
public function get_default_art_kind()
|
||||
{
|
||||
return 'default';
|
||||
}
|
||||
|
||||
public function get_description()
|
||||
{
|
||||
// Album description is not supported yet, always return artist description
|
||||
$artist = new Artist($this->artist_id);
|
||||
return $artist->get_description();
|
||||
}
|
||||
|
||||
public function display_art($thumb = 2)
|
||||
{
|
||||
$id = null;
|
||||
$type = null;
|
||||
|
||||
if (Art::has_db($this->id, 'album')) {
|
||||
$id = $this->id;
|
||||
$type = 'album';
|
||||
} else if (Art::has_db($this->artist_id, 'artist')) {
|
||||
$id = $this->artist_id;
|
||||
$type = 'artist';
|
||||
}
|
||||
|
||||
if ($id !== null && $type !== null) {
|
||||
Art::display($type, $id, $this->get_fullname(), $thumb, $this->link);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get_random_songs
|
||||
* gets a random number, and a random assortment of songs from this album
|
||||
* @return int[]
|
||||
*/
|
||||
public function get_random_songs()
|
||||
{
|
||||
|
@ -481,17 +845,27 @@ class Album extends database_object
|
|||
* update
|
||||
* This function takes a key'd array of data and updates this object
|
||||
* as needed
|
||||
* @param array $data
|
||||
* @return int
|
||||
*/
|
||||
public function update($data)
|
||||
public function update(array $data)
|
||||
{
|
||||
$year = $data['year'];
|
||||
$artist = $data['artist'];
|
||||
$name = $data['name'];
|
||||
$disk = $data['disk'];
|
||||
$mbid = $data['mbid'];
|
||||
$year = isset($data['year']) ? $data['year'] : $this->year;
|
||||
$artist = isset($data['artist']) ? intval($data['artist']) : $this->artist_id;
|
||||
$album_artist = isset($data['album_artist']) ? intval($data['album_artist']) : $this->album_artist;
|
||||
$name = isset($data['name']) ? $data['name'] : $this->name;
|
||||
$disk = isset($data['disk']) ? $data['disk']: $this->disk;
|
||||
$mbid = isset($data['mbid']) ? $data['mbid'] : $this->mbid;
|
||||
$mbid_group = isset($data['mbid_group']) ? $data['mbid_group'] : $this->mbid_group;
|
||||
$release_type = isset($data['release_type']) ? $data['release_type'] : $this->release_type;
|
||||
|
||||
$current_id = $this->id;
|
||||
|
||||
if (!empty($data['album_artist_name'])) {
|
||||
// Need to create new artist according the name
|
||||
$album_artist = Artist::check($data['album_artist_name']);
|
||||
}
|
||||
|
||||
$updated = false;
|
||||
$songs = null;
|
||||
if ($artist != $this->artist_id AND $artist) {
|
||||
|
@ -504,17 +878,31 @@ class Album extends database_object
|
|||
Artist::gc();
|
||||
}
|
||||
|
||||
$album_id = self::check($name, $year, $disk, $mbid);
|
||||
$album_id = self::check($name, $year, $disk, $mbid, $mbid_group, $album_artist, $release_type);
|
||||
if ($album_id != $this->id) {
|
||||
if (!is_array($songs)) { $songs = $this->get_songs(); }
|
||||
foreach ($songs as $song_id) {
|
||||
Song::update_album($album_id,$song_id);
|
||||
Song::update_year($year,$song_id);
|
||||
Song::write_id3_for_song($song_id);
|
||||
}
|
||||
$current_id = $album_id;
|
||||
$updated = true;
|
||||
Stats::migrate('album', $this->id, $album_id);
|
||||
Art::migrate('album', $this->id, $album_id);
|
||||
self::gc();
|
||||
} else {
|
||||
Album::update_year($year, $album_id);
|
||||
Album::update_mbid_group($mbid_group, $album_id);
|
||||
Album::update_release_type($release_type, $album_id);
|
||||
}
|
||||
$this->year = $year;
|
||||
$this->mbid_group = $mbid_group;
|
||||
$this->release_type = $release_type;
|
||||
$this->name = $name;
|
||||
$this->disk = $disk;
|
||||
$this->mbid = $mbid;
|
||||
$this->album_artist = $album_artist;
|
||||
|
||||
if ($updated && is_array($songs)) {
|
||||
foreach ($songs as $song_id) {
|
||||
|
@ -525,11 +913,19 @@ class Album extends database_object
|
|||
Userflag::gc();
|
||||
} // if updated
|
||||
|
||||
$override_songs = false;
|
||||
if ($data['apply_childs'] == 'checked') {
|
||||
$override_songs = true;
|
||||
$override_childs = false;
|
||||
if ($data['overwrite_childs'] == 'checked') {
|
||||
$override_childs = true;
|
||||
}
|
||||
|
||||
$add_to_childs = false;
|
||||
if ($data['add_to_childs'] == 'checked') {
|
||||
$add_to_childs = true;
|
||||
}
|
||||
|
||||
if (isset($data['edit_tags'])) {
|
||||
$this->update_tags($data['edit_tags'], $override_childs, $add_to_childs, $current_id, true);
|
||||
}
|
||||
$this->update_tags($data['edit_tags'], $override_songs, $current_id);
|
||||
|
||||
return $current_id;
|
||||
|
||||
|
@ -539,27 +935,106 @@ class Album extends database_object
|
|||
* update_tags
|
||||
*
|
||||
* Update tags of albums and/or songs
|
||||
* @param string $tags_comma
|
||||
* @param boolean $override_childs
|
||||
* @param boolean $add_to_childs
|
||||
* @param int|null $current_id
|
||||
*/
|
||||
public function update_tags($tags_comma, $override_songs, $current_id = null)
|
||||
public function update_tags($tags_comma, $override_childs, $add_to_childs, $current_id = null, $force_update = false)
|
||||
{
|
||||
if ($current_id == null) {
|
||||
$current_id = $this->id;
|
||||
}
|
||||
|
||||
Tag::update_tag_list($tags_comma, 'album', $current_id);
|
||||
// When current_id not empty we force to overwrite current object
|
||||
Tag::update_tag_list($tags_comma, 'album', $current_id, $force_update ? true : $override_childs);
|
||||
|
||||
if ($override_songs) {
|
||||
if ($override_childs || $add_to_childs) {
|
||||
$songs = $this->get_songs();
|
||||
foreach ($songs as $song_id) {
|
||||
Tag::update_tag_list($tags_comma, 'song', $song_id);
|
||||
Tag::update_tag_list($tags_comma, 'song', $song_id, $override_childs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function remove_from_disk()
|
||||
{
|
||||
$deleted = true;
|
||||
$song_ids = $this->get_songs();
|
||||
foreach ($song_ids as $id) {
|
||||
$song = new Song($id);
|
||||
$deleted = $song->remove_from_disk();
|
||||
if (!$deleted) {
|
||||
debug_event('album', 'Error when deleting the song `' . $id .'`.', 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($deleted) {
|
||||
$sql = "DELETE FROM `album` WHERE `id` = ?";
|
||||
$deleted = Dba::write($sql, array($this->id));
|
||||
if ($deleted) {
|
||||
Art::gc('album', $this->id);
|
||||
Userflag::gc('album', $this->id);
|
||||
Rating::gc('album', $this->id);
|
||||
Shoutbox::gc('album', $this->id);
|
||||
}
|
||||
}
|
||||
|
||||
return $deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update album year.
|
||||
* @param int $year
|
||||
* @param int $album_id
|
||||
*/
|
||||
public static function update_year($year, $album_id)
|
||||
{
|
||||
self::update_field('year', $year, $album_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update album mbid group.
|
||||
* @param string $mbid_group
|
||||
* @param int $album_id
|
||||
*/
|
||||
public static function update_mbid_group($mbid_group, $album_id)
|
||||
{
|
||||
$mbid_group = (!empty($mbid_group)) ? $mbid_group : null;
|
||||
self::update_field('mbid_group', $mbid_group, $album_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update album release type.
|
||||
* @param string $release_type
|
||||
* @param int $album_id
|
||||
*/
|
||||
public static function update_release_type($release_type, $album_id)
|
||||
{
|
||||
$release_type = (!empty($release_type)) ? $release_type : null;
|
||||
self::update_field('release_type', $release_type, $album_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an album field.
|
||||
* @param string $field
|
||||
* @param int $album_id
|
||||
* @return boolean
|
||||
*/
|
||||
private static function update_field($field, $value, $album_id)
|
||||
{
|
||||
$sql = "UPDATE `album` SET `" . $field . "` = ? WHERE `id` = ?";
|
||||
return Dba::write($sql, array($value, $album_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* get_random
|
||||
*
|
||||
* This returns a number of random albums.
|
||||
* @param int $count
|
||||
* @param boolean $with_art
|
||||
* @return int[]
|
||||
*/
|
||||
public static function get_random($count = 1, $with_art = false)
|
||||
{
|
||||
|
@ -569,7 +1044,7 @@ class Album extends database_object
|
|||
$count = 1;
|
||||
}
|
||||
|
||||
$sql = "SELECT `album`.`id` FROM `album` " .
|
||||
$sql = "SELECT DISTINCT `album`.`id` FROM `album` " .
|
||||
"LEFT JOIN `song` ON `song`.`album` = `album`.`id` ";
|
||||
if (AmpConfig::get('catalog_disable')) {
|
||||
$sql .= "LEFT JOIN `catalog` ON `catalog`.`id` = `song`.`catalog` ";
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -27,6 +27,9 @@
|
|||
*/
|
||||
class Ampache_RSS
|
||||
{
|
||||
/**
|
||||
* @var string $type
|
||||
*/
|
||||
private $type;
|
||||
public $data;
|
||||
|
||||
|
@ -44,33 +47,56 @@ class Ampache_RSS
|
|||
* get_xml
|
||||
* This returns the xmldocument for the current rss type, it calls a sub function that gathers the data
|
||||
* and then uses the xmlDATA class to build the document
|
||||
* @return string
|
||||
*/
|
||||
public function get_xml()
|
||||
public function get_xml($params = null)
|
||||
{
|
||||
// Function call name
|
||||
$data_function = 'load_' . $this->type;
|
||||
$pub_date_function = 'pubdate_' . $this->type;
|
||||
if ($this->type === "podcast") {
|
||||
if ($params != null && is_array($params)) {
|
||||
$object_type = $params['object_type'];
|
||||
$object_id = $params['object_id'];
|
||||
if (Core::is_library_item($object_type)) {
|
||||
$libitem = new $object_type($object_id);
|
||||
if ($libitem->id) {
|
||||
$libitem->format();
|
||||
return XML_Data::podcast($libitem);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Function call name
|
||||
$data_function = 'load_' . $this->type;
|
||||
$pub_date_function = 'pubdate_' . $this->type;
|
||||
|
||||
$data = call_user_func(array('Ampache_RSS',$data_function));
|
||||
$pub_date = call_user_func(array('Ampache_RSS',$pub_date_function));
|
||||
$data = call_user_func(array('Ampache_RSS',$data_function));
|
||||
$pub_date = null;
|
||||
if (method_exists('Ampache_RSS', $data_function)) {
|
||||
$pub_date = call_user_func(array('Ampache_RSS',$pub_date_function));
|
||||
}
|
||||
|
||||
XML_Data::set_type('rss');
|
||||
$xml_document = XML_Data::rss_feed($data,$this->get_title(),$this->get_description(),$pub_date);
|
||||
XML_Data::set_type('rss');
|
||||
$xml_document = XML_Data::rss_feed($data,$this->get_title(),$this->get_description(),$pub_date);
|
||||
|
||||
return $xml_document;
|
||||
return $xml_document;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
} // get_xml
|
||||
|
||||
/**
|
||||
* get_title
|
||||
* This returns the standardized title for the rss feed based on this->type
|
||||
* @return string
|
||||
*/
|
||||
public function get_title()
|
||||
{
|
||||
$titles = array('now_playing' => T_('Now Playing'),
|
||||
'recently_played' => T_('Recently Played'),
|
||||
'latest_album' => T_('Newest Albums'),
|
||||
'latest_artist' => T_('Newest Artists'));
|
||||
'recently_played' => T_('Recently Played'),
|
||||
'latest_album' => T_('Newest Albums'),
|
||||
'latest_artist' => T_('Newest Artists'),
|
||||
'latest_shout' => T_('Newest Shouts')
|
||||
);
|
||||
|
||||
return scrub_out(AmpConfig::get('site_title')) . ' - ' . $titles[$this->type];
|
||||
|
||||
|
@ -79,6 +105,7 @@ class Ampache_RSS
|
|||
/**
|
||||
* get_description
|
||||
* This returns the standardized description for the rss feed based on this->type
|
||||
* @return string
|
||||
*/
|
||||
public function get_description()
|
||||
{
|
||||
|
@ -90,11 +117,12 @@ class Ampache_RSS
|
|||
/**
|
||||
* validate_type
|
||||
* this returns a valid type for an rss feed, if the specified type is invalid it returns a default value
|
||||
* @param string $type
|
||||
* @return string
|
||||
*/
|
||||
public static function validate_type($type)
|
||||
{
|
||||
$valid_types = array('now_playing','recently_played','latest_album','latest_artist','latest_song',
|
||||
'popular_song','popular_album','popular_artist');
|
||||
$valid_types = array('now_playing','recently_played','latest_album','latest_artist','latest_shout','podcast');
|
||||
|
||||
if (!in_array($type,$valid_types)) {
|
||||
return 'now_playing';
|
||||
|
@ -107,13 +135,28 @@ class Ampache_RSS
|
|||
/**
|
||||
* get_display
|
||||
* This dumps out some html and an icon for the type of rss that we specify
|
||||
* @param string $type
|
||||
* @param string $title
|
||||
* @param array|null $params
|
||||
* @return string
|
||||
*/
|
||||
public static function get_display($type='now_playing')
|
||||
public static function get_display($type='now_playing', $title = '', $params = null)
|
||||
{
|
||||
// Default to now playing
|
||||
$type = self::validate_type($type);
|
||||
|
||||
$string = '<a href="' . AmpConfig::get('web_path') . '/rss.php?type=' . $type . '">' . UI::get_icon('feed', T_('RSS Feed')) . '</a>';
|
||||
$strparams = "";
|
||||
if ($params != null && is_array($params)) {
|
||||
foreach ($params as $key => $value) {
|
||||
$strparams .= "&" . scrub_out($key) . "=" . scrub_out($value);
|
||||
}
|
||||
}
|
||||
|
||||
$string = '<a rel="nohtml" href="' . AmpConfig::get('web_path') . '/rss.php?type=' . $type . $strparams . '">' . UI::get_icon('feed', T_('RSS Feed'));
|
||||
if (!empty($title)) {
|
||||
$string .= ' ' . $title;
|
||||
}
|
||||
$string .= '</a>';
|
||||
|
||||
return $string;
|
||||
|
||||
|
@ -125,6 +168,7 @@ class Ampache_RSS
|
|||
* load_now_playing
|
||||
* This loads in the now playing information. This is just the raw data with key=>value pairs that could be turned
|
||||
* into an xml document if we so wished
|
||||
* @return array
|
||||
*/
|
||||
public static function load_now_playing()
|
||||
{
|
||||
|
@ -152,7 +196,7 @@ class Ampache_RSS
|
|||
'title' => $title,
|
||||
'link' => $song->link,
|
||||
'description' => $description,
|
||||
'comments' => $client->fullname . ' - ' . $element['agent'],
|
||||
'comments' => $client->f_name . ' - ' . $element['agent'],
|
||||
'pubDate' => date('r', $element['expire'])
|
||||
);
|
||||
$results[] = $xml_array;
|
||||
|
@ -166,6 +210,7 @@ class Ampache_RSS
|
|||
* pubdate_now_playing
|
||||
* this is the pub date we should use for the now playing information,
|
||||
* this is a little specific as it uses the 'newest' expire we can find
|
||||
* @return int
|
||||
*/
|
||||
public static function pubdate_now_playing()
|
||||
{
|
||||
|
@ -181,6 +226,7 @@ class Ampache_RSS
|
|||
/**
|
||||
* load_recently_played
|
||||
* This loads in the recently played information and formats it up real nice like
|
||||
* @return array
|
||||
*/
|
||||
public static function load_recently_played()
|
||||
{
|
||||
|
@ -237,9 +283,104 @@ class Ampache_RSS
|
|||
|
||||
} // load_recently_played
|
||||
|
||||
/**
|
||||
* load_latest_album
|
||||
* This loads in the latest added albums
|
||||
* @return array
|
||||
*/
|
||||
public static function load_latest_album()
|
||||
{
|
||||
$ids = Stats::get_newest('album', 10);
|
||||
|
||||
$results = array();
|
||||
|
||||
foreach ($ids as $id) {
|
||||
$album = new Album($id);
|
||||
$album->format();
|
||||
|
||||
$xml_array = array('title' => $album->f_name,
|
||||
'link' => $album->link,
|
||||
'description' => $album->f_artist_name . ' - ' . $album->f_name,
|
||||
'image' => Art::url($album->id, 'album', null, 2),
|
||||
'comments' => '',
|
||||
'pubDate' => date("c", $album->get_addtime_first_song())
|
||||
);
|
||||
$results[] = $xml_array;
|
||||
|
||||
} // end foreach
|
||||
|
||||
return $results;
|
||||
|
||||
} // load_latest_album
|
||||
|
||||
/**
|
||||
* load_latest_artist
|
||||
* This loads in the latest added artists
|
||||
* @return array
|
||||
*/
|
||||
public static function load_latest_artist()
|
||||
{
|
||||
$ids = Stats::get_newest('artist', 10);
|
||||
|
||||
$results = array();
|
||||
|
||||
foreach ($ids as $id) {
|
||||
$artist = new Artist($id);
|
||||
$artist->format();
|
||||
|
||||
$xml_array = array('title' => $artist->f_name,
|
||||
'link' => $artist->link,
|
||||
'description' => $artist->summary,
|
||||
'image' => Art::url($artist->id, 'artist', null, 2),
|
||||
'comments' => '',
|
||||
'pubDate' => ''
|
||||
);
|
||||
$results[] = $xml_array;
|
||||
|
||||
} // end foreach
|
||||
|
||||
return $results;
|
||||
|
||||
} // load_latest_artist
|
||||
|
||||
/**
|
||||
* load_latest_shout
|
||||
* This loads in the latest added shouts
|
||||
* @return array
|
||||
*/
|
||||
public static function load_latest_shout()
|
||||
{
|
||||
$ids = Shoutbox::get_top(10);
|
||||
|
||||
$results = array();
|
||||
|
||||
foreach ($ids as $id) {
|
||||
$shout = new Shoutbox($id);
|
||||
$shout->format();
|
||||
$object = Shoutbox::get_object($shout->object_type, $shout->object_id);
|
||||
$object->format();
|
||||
$user = new User($shout->user);
|
||||
$user->format();
|
||||
|
||||
$xml_array = array('title' => $user->username . ' ' . T_('on') . ' ' . $object->get_fullname(),
|
||||
'link' => $object->link,
|
||||
'description' => $shout->text,
|
||||
'image' => Art::url($shout->object_id, $shout->object_type, null, 2),
|
||||
'comments' => '',
|
||||
'pubDate' => date("c", $shout->date)
|
||||
);
|
||||
$results[] = $xml_array;
|
||||
|
||||
} // end foreach
|
||||
|
||||
return $results;
|
||||
|
||||
} // load_latest_shout
|
||||
|
||||
/**
|
||||
* pubdate_recently_played
|
||||
* This just returns the 'newest' recently played entry
|
||||
* @return int
|
||||
*/
|
||||
public static function pubdate_recently_played()
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -35,6 +35,9 @@
|
|||
*/
|
||||
class AmpConfig
|
||||
{
|
||||
/**
|
||||
* @var array $_global
|
||||
*/
|
||||
private static $_global = array();
|
||||
|
||||
public function __construct()
|
||||
|
@ -46,6 +49,7 @@ class AmpConfig
|
|||
* get
|
||||
*
|
||||
* This returns a config value.
|
||||
* @param string $name
|
||||
*/
|
||||
public static function get($name)
|
||||
{
|
||||
|
@ -60,6 +64,7 @@ class AmpConfig
|
|||
* get_all
|
||||
*
|
||||
* This returns all of the current config variables as an array.
|
||||
* @return array
|
||||
*/
|
||||
public static function get_all()
|
||||
{
|
||||
|
@ -70,6 +75,8 @@ class AmpConfig
|
|||
* set
|
||||
*
|
||||
* This sets config values.
|
||||
* @param string $name
|
||||
* @param boolean $clobber
|
||||
*/
|
||||
public static function set($name, $value, $clobber = false)
|
||||
{
|
||||
|
@ -87,6 +94,8 @@ class AmpConfig
|
|||
*
|
||||
* This is the same as the set function except it takes an array as
|
||||
* input.
|
||||
* @param array $array
|
||||
* @param boolean $clobber
|
||||
*/
|
||||
public static function set_by_array($array, $clobber = false)
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -30,9 +30,18 @@
|
|||
*/
|
||||
class Api
|
||||
{
|
||||
/**
|
||||
* @var string $auth_version
|
||||
*/
|
||||
public static $auth_version = '350001';
|
||||
public static $version = '370001';
|
||||
/**
|
||||
* @var string $version
|
||||
*/
|
||||
public static $version = '380001';
|
||||
|
||||
/**
|
||||
* @var Browse $browse
|
||||
*/
|
||||
private static $browse = null;
|
||||
|
||||
/**
|
||||
|
@ -62,6 +71,9 @@ class Api
|
|||
* the filters in a slightly different and vastly simpler way to the
|
||||
* end users--so we have to do a little extra work to make them work
|
||||
* internally.
|
||||
* @param string $filter
|
||||
* @param int|string|boolean|null $value
|
||||
* @return boolean
|
||||
*/
|
||||
public static function set_filter($filter,$value)
|
||||
{
|
||||
|
@ -108,6 +120,8 @@ class Api
|
|||
*
|
||||
* This is the function that handles verifying a new handshake
|
||||
* Takes a timestamp, auth key, and username.
|
||||
* @param array
|
||||
* @return boolean
|
||||
*/
|
||||
public static function handshake($input)
|
||||
{
|
||||
|
@ -155,6 +169,7 @@ class Api
|
|||
($timestamp > (time() + 1800))) {
|
||||
debug_event('API', 'Login Failed: timestamp out of range ' . $timestamp . '/' . time(), 1);
|
||||
Error::add('api', T_('Login Failed: timestamp out of range'));
|
||||
echo XML_Data::error('401', T_('Error Invalid Handshake - ') . T_('Login Failed: timestamp out of range'));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -166,6 +181,7 @@ class Api
|
|||
if (!$realpwd) {
|
||||
debug_event('API', 'Unable to find user with userid of ' . $user_id, 1);
|
||||
Error::add('api', T_('Invalid Username/Password'));
|
||||
echo XML_Data::error('401', T_('Error Invalid Handshake - ') . T_('Invalid Username/Password'));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -184,6 +200,18 @@ class Api
|
|||
$data['username'] = $client->username;
|
||||
$data['type'] = 'api';
|
||||
$data['value'] = $timestamp;
|
||||
if (isset($input['client'])) {
|
||||
$data['agent'] = $input['client'];
|
||||
}
|
||||
if (isset($input['geo_latitude'])) {
|
||||
$data['geo_latitude'] = $input['geo_latitude'];
|
||||
}
|
||||
if (isset($input['geo_longitude'])) {
|
||||
$data['geo_longitude'] = $input['geo_longitude'];
|
||||
}
|
||||
if (isset($input['geo_name'])) {
|
||||
$data['geo_name'] = $input['geo_name'];
|
||||
}
|
||||
$token = Session::create($data);
|
||||
|
||||
debug_event('API', 'Login Success, passphrase matched', 1);
|
||||
|
@ -233,14 +261,16 @@ class Api
|
|||
} // end while
|
||||
|
||||
debug_event('API','Login Failed, unable to match passphrase','1');
|
||||
XML_Data::error('401', T_('Error Invalid Handshake - ') . T_('Invalid Username/Password'));
|
||||
echo XML_Data::error('401', T_('Error Invalid Handshake - ') . T_('Invalid Username/Password'));
|
||||
|
||||
return false;
|
||||
} // handshake
|
||||
|
||||
/**
|
||||
* ping
|
||||
* This can be called without being authenticated, it is useful for determining if what the status
|
||||
* of the server is, and what version it is running/compatible with
|
||||
* @param array $input
|
||||
*/
|
||||
public static function ping($input)
|
||||
{
|
||||
|
@ -264,6 +294,7 @@ class Api
|
|||
* This takes a collection of inputs and returns
|
||||
* artist objects. This function is deprecated!
|
||||
* //DEPRECATED
|
||||
* @param array $input
|
||||
*/
|
||||
public static function artists($input)
|
||||
{
|
||||
|
@ -291,6 +322,7 @@ class Api
|
|||
* artist
|
||||
* This returns a single artist based on the UID of said artist
|
||||
* //DEPRECATED
|
||||
* @param array $input
|
||||
*/
|
||||
public static function artist($input)
|
||||
{
|
||||
|
@ -302,6 +334,7 @@ class Api
|
|||
/**
|
||||
* artist_albums
|
||||
* This returns the albums of an artist
|
||||
* @param array $input
|
||||
*/
|
||||
public static function artist_albums($input)
|
||||
{
|
||||
|
@ -320,6 +353,7 @@ class Api
|
|||
/**
|
||||
* artist_songs
|
||||
* This returns the songs of the specified artist
|
||||
* @param array $input
|
||||
*/
|
||||
public static function artist_songs($input)
|
||||
{
|
||||
|
@ -337,6 +371,7 @@ class Api
|
|||
/**
|
||||
* albums
|
||||
* This returns albums based on the provided search filters
|
||||
* @param array $input
|
||||
*/
|
||||
public static function albums($input)
|
||||
{
|
||||
|
@ -361,6 +396,7 @@ class Api
|
|||
/**
|
||||
* album
|
||||
* This returns a single album based on the UID provided
|
||||
* @param array $input
|
||||
*/
|
||||
public static function album($input)
|
||||
{
|
||||
|
@ -372,6 +408,7 @@ class Api
|
|||
/**
|
||||
* album_songs
|
||||
* This returns the songs of a specified album
|
||||
* @param array $input
|
||||
*/
|
||||
public static function album_songs($input)
|
||||
{
|
||||
|
@ -390,6 +427,7 @@ class Api
|
|||
/**
|
||||
* tags
|
||||
* This returns the tags based on the specified filter
|
||||
* @param array $input
|
||||
*/
|
||||
public static function tags($input)
|
||||
{
|
||||
|
@ -413,6 +451,7 @@ class Api
|
|||
/**
|
||||
* tag
|
||||
* This returns a single tag based on UID
|
||||
* @param array $input
|
||||
*/
|
||||
public static function tag($input)
|
||||
{
|
||||
|
@ -425,38 +464,43 @@ class Api
|
|||
/**
|
||||
* tag_artists
|
||||
* This returns the artists associated with the tag in question as defined by the UID
|
||||
* @param array $input
|
||||
*/
|
||||
public static function tag_artists($input)
|
||||
{
|
||||
$artists = Tag::get_tag_objects('artist',$input['filter']);
|
||||
if ($artists) {
|
||||
XML_Data::set_offset($input['offset']);
|
||||
XML_Data::set_limit($input['limit']);
|
||||
|
||||
XML_Data::set_offset($input['offset']);
|
||||
XML_Data::set_limit($input['limit']);
|
||||
|
||||
ob_end_clean();
|
||||
echo XML_Data::artists($artists);
|
||||
ob_end_clean();
|
||||
echo XML_Data::artists($artists);
|
||||
}
|
||||
|
||||
} // tag_artists
|
||||
|
||||
/**
|
||||
* tag_albums
|
||||
* This returns the albums associated with the tag in question
|
||||
* @param array $input
|
||||
*/
|
||||
public static function tag_albums($input)
|
||||
{
|
||||
$albums = Tag::get_tag_objects('album',$input['filter']);
|
||||
if ($albums) {
|
||||
XML_Data::set_offset($input['offset']);
|
||||
XML_Data::set_limit($input['limit']);
|
||||
|
||||
XML_Data::set_offset($input['offset']);
|
||||
XML_Data::set_limit($input['limit']);
|
||||
|
||||
ob_end_clean();
|
||||
echo XML_Data::albums($albums);
|
||||
ob_end_clean();
|
||||
echo XML_Data::albums($albums);
|
||||
}
|
||||
|
||||
} // tag_albums
|
||||
|
||||
/**
|
||||
* tag_songs
|
||||
* returns the songs for this tag
|
||||
* @param array $input
|
||||
*/
|
||||
public static function tag_songs($input)
|
||||
{
|
||||
|
@ -473,6 +517,7 @@ class Api
|
|||
/**
|
||||
* songs
|
||||
* Returns songs based on the specified filter
|
||||
* @param array $input
|
||||
*/
|
||||
public static function songs($input)
|
||||
{
|
||||
|
@ -499,6 +544,7 @@ class Api
|
|||
/**
|
||||
* song
|
||||
* returns a single song
|
||||
* @param array $input
|
||||
*/
|
||||
public static function song($input)
|
||||
{
|
||||
|
@ -513,6 +559,7 @@ class Api
|
|||
* url_to_song
|
||||
*
|
||||
* This takes a url and returns the song object in question
|
||||
* @param array $input
|
||||
*/
|
||||
public static function url_to_song($input)
|
||||
{
|
||||
|
@ -525,6 +572,7 @@ class Api
|
|||
/**
|
||||
* playlists
|
||||
* This returns playlists based on the specified filter
|
||||
* @param array $input
|
||||
*/
|
||||
public static function playlists($input)
|
||||
{
|
||||
|
@ -548,6 +596,7 @@ class Api
|
|||
/**
|
||||
* playlist
|
||||
* This returns a single playlist
|
||||
* @param array $input
|
||||
*/
|
||||
public static function playlist($input)
|
||||
{
|
||||
|
@ -561,6 +610,7 @@ class Api
|
|||
/**
|
||||
* playlist_songs
|
||||
* This returns the songs for a playlist
|
||||
* @param array $input
|
||||
*/
|
||||
public static function playlist_songs($input)
|
||||
{
|
||||
|
@ -577,13 +627,14 @@ class Api
|
|||
XML_Data::set_offset($input['offset']);
|
||||
XML_Data::set_limit($input['limit']);
|
||||
ob_end_clean();
|
||||
echo XML_Data::songs($songs);
|
||||
echo XML_Data::songs($songs,$items);
|
||||
|
||||
} // playlist_songs
|
||||
|
||||
/**
|
||||
* playlist_create
|
||||
* This create a new playlist and return it
|
||||
* @param array $input
|
||||
*/
|
||||
public static function playlist_create($input)
|
||||
{
|
||||
|
@ -600,6 +651,7 @@ class Api
|
|||
/**
|
||||
* playlist_delete
|
||||
* This delete a playlist
|
||||
* @param array $input
|
||||
*/
|
||||
public static function playlist_delete($input)
|
||||
{
|
||||
|
@ -616,12 +668,13 @@ class Api
|
|||
/**
|
||||
* playlist_add_song
|
||||
* This add a song to a playlist
|
||||
* @param array $input
|
||||
*/
|
||||
public static function playlist_add_song($input)
|
||||
{
|
||||
ob_end_clean();
|
||||
$playlist = new Playlist($input['filter']);
|
||||
$song = new Playlist($input['song']);
|
||||
$song = $input['song'];
|
||||
if (!$playlist->has_access()) {
|
||||
echo XML_Data::error('401', T_('Access denied to this playlist.'));
|
||||
} else {
|
||||
|
@ -634,12 +687,13 @@ class Api
|
|||
/**
|
||||
* playlist_remove_song
|
||||
* This remove a song from a playlist
|
||||
* @param array $input
|
||||
*/
|
||||
public static function playlist_remove_song($input)
|
||||
{
|
||||
ob_end_clean();
|
||||
$playlist = new Playlist($input['filter']);
|
||||
$track = new Playlist($input['track']);
|
||||
$track = scrub_in($input['track']);
|
||||
if (!$playlist->has_access()) {
|
||||
echo XML_Data::error('401', T_('Access denied to this playlist.'));
|
||||
} else {
|
||||
|
@ -652,6 +706,7 @@ class Api
|
|||
/**
|
||||
* search_songs
|
||||
* This searches the songs and returns... songs
|
||||
* @param array $input
|
||||
*/
|
||||
public static function search_songs($input)
|
||||
{
|
||||
|
@ -675,6 +730,7 @@ class Api
|
|||
/**
|
||||
* videos
|
||||
* This returns video objects!
|
||||
* @param array $input
|
||||
*/
|
||||
public static function videos($input)
|
||||
{
|
||||
|
@ -697,6 +753,7 @@ class Api
|
|||
/**
|
||||
* video
|
||||
* This returns a single video
|
||||
* @param array $input
|
||||
*/
|
||||
public static function video($input)
|
||||
{
|
||||
|
@ -710,6 +767,7 @@ class Api
|
|||
/**
|
||||
* localplay
|
||||
* This is for controling localplay
|
||||
* @param array $input
|
||||
*/
|
||||
public static function localplay($input)
|
||||
{
|
||||
|
@ -737,6 +795,7 @@ class Api
|
|||
/**
|
||||
* democratic
|
||||
* This is for controlling democratic play
|
||||
* @param array $input
|
||||
*/
|
||||
public static function democratic($input)
|
||||
{
|
||||
|
@ -781,7 +840,7 @@ class Api
|
|||
$objects = $democratic->get_items();
|
||||
Song::build_cache($democratic->object_ids);
|
||||
Democratic::build_vote_cache($democratic->vote_ids);
|
||||
XML_Data::democratic($objects);
|
||||
echo XML_Data::democratic($objects);
|
||||
break;
|
||||
case 'play':
|
||||
$url = $democratic->play_url();
|
||||
|
@ -795,12 +854,18 @@ class Api
|
|||
|
||||
} // democratic
|
||||
|
||||
/**
|
||||
* This get library stats.
|
||||
* @param array $input
|
||||
*/
|
||||
public static function stats($input)
|
||||
{
|
||||
$type = $input['type'];
|
||||
$offset = $input['offset'];
|
||||
$limit = $input['limit'];
|
||||
$username = $input['username'];
|
||||
|
||||
$albums = null;
|
||||
if ($type == "newest") {
|
||||
$albums = Stats::get_newest("album", $limit, $offset);
|
||||
} else if ($type == "highest") {
|
||||
|
@ -808,7 +873,16 @@ class Api
|
|||
} else if ($type == "frequent") {
|
||||
$albums = Stats::get_top("album", $limit, '', $offset);
|
||||
} else if ($type == "recent") {
|
||||
$albums = Stats::get_recent("album", $limit, $offset);
|
||||
if (!empty($username)) {
|
||||
$user = User::get_from_username($username);
|
||||
if ($user !== null) {
|
||||
$albums = $user->get_recently_played($limit, 'album');
|
||||
} else {
|
||||
debug_event('api', 'User `' . $username . '` cannot be found.', 1);
|
||||
}
|
||||
} else {
|
||||
$albums = Stats::get_recent("album", $limit, $offset);
|
||||
}
|
||||
} else if ($type == "flagged") {
|
||||
$albums = Userflag::get_latest('album');
|
||||
} else {
|
||||
|
@ -818,8 +892,109 @@ class Api
|
|||
$albums = Album::get_random($limit);
|
||||
}
|
||||
|
||||
ob_end_clean();
|
||||
echo XML_Data::albums($albums);
|
||||
}
|
||||
if ($albums !== null) {
|
||||
ob_end_clean();
|
||||
echo XML_Data::albums($albums);
|
||||
}
|
||||
} // stats
|
||||
|
||||
/**
|
||||
* user
|
||||
* This get an user public information
|
||||
* @param array $input
|
||||
*/
|
||||
public static function user($input)
|
||||
{
|
||||
$username = $input['username'];
|
||||
if (!empty($username)) {
|
||||
$user = User::get_from_username($username);
|
||||
if ($user !== null) {
|
||||
ob_end_clean();
|
||||
echo XML_Data::user($user);
|
||||
} else {
|
||||
debug_event('api', 'User `' . $username . '` cannot be found.', 1);
|
||||
}
|
||||
} else {
|
||||
debug_event('api', 'Username required on user function call.', 1);
|
||||
}
|
||||
} // user
|
||||
|
||||
/**
|
||||
* followers
|
||||
* This get an user followers
|
||||
* @param array $input
|
||||
*/
|
||||
public static function followers($input)
|
||||
{
|
||||
if (AmpConfig::get('sociable')) {
|
||||
$username = $input['username'];
|
||||
if (!empty($username)) {
|
||||
$user = User::get_from_username($username);
|
||||
if ($user !== null) {
|
||||
$users = $user->get_followers();
|
||||
ob_end_clean();
|
||||
echo XML_Data::users($user);
|
||||
} else {
|
||||
debug_event('api', 'User `' . $username . '` cannot be found.', 1);
|
||||
}
|
||||
} else {
|
||||
debug_event('api', 'Username required on followers function call.', 1);
|
||||
}
|
||||
} else {
|
||||
debug_event('api', 'Sociable feature is not enabled.', 3);
|
||||
}
|
||||
} // followers
|
||||
|
||||
/**
|
||||
* following
|
||||
* This get the user list followed by an user
|
||||
* @param array $input
|
||||
*/
|
||||
public static function following($input)
|
||||
{
|
||||
if (AmpConfig::get('sociable')) {
|
||||
$username = $input['username'];
|
||||
if (!empty($username)) {
|
||||
$user = User::get_from_username($username);
|
||||
if ($user !== null) {
|
||||
$users = $user->get_following();
|
||||
ob_end_clean();
|
||||
echo XML_Data::users($user);
|
||||
} else {
|
||||
debug_event('api', 'User `' . $username . '` cannot be found.', 1);
|
||||
}
|
||||
} else {
|
||||
debug_event('api', 'Username required on following function call.', 1);
|
||||
}
|
||||
} else {
|
||||
debug_event('api', 'Sociable feature is not enabled.', 3);
|
||||
}
|
||||
} // following
|
||||
|
||||
/**
|
||||
* last_shouts
|
||||
* This get the latest posted shouts
|
||||
* @param array $input
|
||||
*/
|
||||
public static function last_shouts($input)
|
||||
{
|
||||
$limit = intval($input['limit']);
|
||||
if ($limit < 1) {
|
||||
$limit = AmpConfig::get('popular_threshold');
|
||||
}
|
||||
if (AmpConfig::get('sociable')) {
|
||||
$username = $input['username'];
|
||||
if (!empty($username)) {
|
||||
$shouts = Shoutbox::get_top($limit, $username);
|
||||
} else {
|
||||
$shouts = Shoutbox::get_top($limit);
|
||||
}
|
||||
|
||||
ob_end_clean();
|
||||
echo XML_Data::shouts($shouts);
|
||||
} else {
|
||||
debug_event('api', 'Sociable feature is not enabled.', 3);
|
||||
}
|
||||
} // last_shouts
|
||||
|
||||
} // API class
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -20,42 +20,123 @@
|
|||
*
|
||||
*/
|
||||
|
||||
class Artist extends database_object
|
||||
class Artist extends database_object implements library_item
|
||||
{
|
||||
/* Variables from DB */
|
||||
public $id;
|
||||
public $name;
|
||||
public $summary;
|
||||
public $placeformed;
|
||||
public $yearformed;
|
||||
public $last_update;
|
||||
public $songs;
|
||||
public $albums;
|
||||
public $prefix;
|
||||
public $mbid; // MusicBrainz ID
|
||||
public $catalog_id;
|
||||
public $time;
|
||||
|
||||
/**
|
||||
* @var int $id
|
||||
*/
|
||||
public $id;
|
||||
/**
|
||||
* @var string $name
|
||||
*/
|
||||
public $name;
|
||||
/**
|
||||
* @var string $summary
|
||||
*/
|
||||
public $summary;
|
||||
/**
|
||||
* @var string $placeformed
|
||||
*/
|
||||
public $placeformed;
|
||||
/**
|
||||
* @var int $yearformed
|
||||
*/
|
||||
public $yearformed;
|
||||
/**
|
||||
* @var int $last_update
|
||||
*/
|
||||
public $last_update;
|
||||
/**
|
||||
* @var int $songs
|
||||
*/
|
||||
public $songs;
|
||||
/**
|
||||
* @var int $albums
|
||||
*/
|
||||
public $albums;
|
||||
/**
|
||||
* @var string $prefix
|
||||
*/
|
||||
public $prefix;
|
||||
/**
|
||||
* @var string $mbid
|
||||
*/
|
||||
public $mbid; // MusicBrainz ID
|
||||
/**
|
||||
* @var int $catalog_id
|
||||
*/
|
||||
public $catalog_id;
|
||||
/**
|
||||
* @var int $time
|
||||
*/
|
||||
public $time;
|
||||
/**
|
||||
* @var int $user
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* @var array $tags
|
||||
*/
|
||||
public $tags;
|
||||
/**
|
||||
* @var string $f_tags
|
||||
*/
|
||||
public $f_tags;
|
||||
/**
|
||||
* @var array $labels
|
||||
*/
|
||||
public $labels;
|
||||
/**
|
||||
* @var string $f_labels
|
||||
*/
|
||||
public $f_labels;
|
||||
/**
|
||||
* @var int $object_cnt
|
||||
*/
|
||||
public $object_cnt;
|
||||
/**
|
||||
* @var string $f_name
|
||||
*/
|
||||
public $f_name;
|
||||
/**
|
||||
* @var string $f_full_name
|
||||
*/
|
||||
public $f_full_name;
|
||||
/**
|
||||
* @var string $link
|
||||
*/
|
||||
public $link;
|
||||
/**
|
||||
* @var string $f_link
|
||||
*/
|
||||
public $f_link;
|
||||
public $f_name_link;
|
||||
/**
|
||||
* @var string $f_time
|
||||
*/
|
||||
public $f_time;
|
||||
|
||||
|
||||
// Constructed vars
|
||||
/**
|
||||
* @var boolean $_fake
|
||||
*/
|
||||
public $_fake = false; // Set if construct_from_array() used
|
||||
/**
|
||||
* @var array $_mapcache
|
||||
*/
|
||||
private static $_mapcache = array();
|
||||
|
||||
/**
|
||||
* Artist
|
||||
* Artist class, for modifing a artist
|
||||
* Takes the ID of the artist and pulls the info from the db
|
||||
* @param int|null $id
|
||||
* @param int $catalog_init
|
||||
*/
|
||||
public function __construct($id='',$catalog_init=0)
|
||||
public function __construct($id=null,$catalog_init=0)
|
||||
{
|
||||
/* If they failed to pass in an id, just run for it */
|
||||
if (!$id) { return false; }
|
||||
|
@ -76,6 +157,8 @@ class Artist extends database_object
|
|||
* construct_from_array
|
||||
* This is used by the metadata class specifically but fills out a Artist object
|
||||
* based on a key'd array, it sets $_fake to true
|
||||
* @param array $data
|
||||
* @return Artist
|
||||
*/
|
||||
public static function construct_from_array($data)
|
||||
{
|
||||
|
@ -98,13 +181,20 @@ class Artist extends database_object
|
|||
*/
|
||||
public static function gc()
|
||||
{
|
||||
Dba::write('DELETE FROM `artist` USING `artist` LEFT JOIN `song` ON `song`.`artist` = `artist`.`id` LEFT JOIN `wanted` ON `wanted`.`artist` = `artist`.`id` WHERE `song`.`id` IS NULL AND `wanted`.`id` IS NULL');
|
||||
Dba::write('DELETE FROM `artist` USING `artist` LEFT JOIN `song` ON `song`.`artist` = `artist`.`id` ' .
|
||||
'LEFT JOIN `album` ON `album`.`album_artist` = `artist`.`id` ' .
|
||||
'LEFT JOIN `wanted` ON `wanted`.`artist` = `artist`.`id` ' .
|
||||
'LEFT JOIN `clip` ON `clip`.`artist` = `artist`.`id` ' .
|
||||
'WHERE `song`.`id` IS NULL AND `album`.`id` IS NULL AND `wanted`.`id` IS NULL AND `clip`.`id` IS NULL');
|
||||
}
|
||||
|
||||
/**
|
||||
* this attempts to build a cache of the data from the passed albums all in one query
|
||||
* @param int[] $ids
|
||||
* @param boolean $extra
|
||||
* @return boolean
|
||||
*/
|
||||
public static function build_cache($ids,$extra=false)
|
||||
public static function build_cache($ids, $extra=false, $limit_threshold = '')
|
||||
{
|
||||
if (!is_array($ids) OR !count($ids)) { return false; }
|
||||
|
||||
|
@ -119,14 +209,14 @@ class Artist extends database_object
|
|||
|
||||
// If we need to also pull the extra information, this is normally only used when we are doing the human display
|
||||
if ($extra) {
|
||||
$sql = "SELECT `song`.`artist`, COUNT(`song`.`id`) AS `song_count`, COUNT(DISTINCT `song`.`album`) AS `album_count`, SUM(`song`.`time`) AS `time` FROM `song` WHERE `song`.`artist` IN $idlist GROUP BY `song`.`artist`";
|
||||
$sql = "SELECT `song`.`artist`, COUNT(DISTINCT `song`.`id`) AS `song_count`, COUNT(DISTINCT `song`.`album`) AS `album_count`, SUM(`song`.`time`) AS `time` FROM `song` WHERE `song`.`artist` IN $idlist GROUP BY `song`.`artist`";
|
||||
|
||||
debug_event("Artist", "build_cache sql: " . $sql, "6");
|
||||
$db_results = Dba::read($sql);
|
||||
|
||||
while ($row = Dba::fetch_assoc($db_results)) {
|
||||
if (AmpConfig::get('show_played_times')) {
|
||||
$row['object_cnt'] = Stats::get_object_count('artist', $row['artist']);
|
||||
$row['object_cnt'] = Stats::get_object_count('artist', $row['artist'], $limit_threshold);
|
||||
}
|
||||
parent::add_to_cache('artist_extra',$row['artist'],$row);
|
||||
}
|
||||
|
@ -140,6 +230,8 @@ class Artist extends database_object
|
|||
/**
|
||||
* get_from_name
|
||||
* This gets an artist object based on the artist name
|
||||
* @param string $name
|
||||
* @return Artist
|
||||
*/
|
||||
public static function get_from_name($name)
|
||||
{
|
||||
|
@ -158,13 +250,17 @@ class Artist extends database_object
|
|||
* get_albums
|
||||
* gets the album ids that this artist is a part
|
||||
* of
|
||||
* @param int|null $catalog
|
||||
* @param boolean $ignoreAlbumGroups
|
||||
* @param boolean $group_release_type
|
||||
* @return int[]
|
||||
*/
|
||||
public function get_albums($catalog = null, $ignoreAlbumGroups = false)
|
||||
public function get_albums($catalog = null, $ignoreAlbumGroups = false, $group_release_type = false)
|
||||
{
|
||||
$catalog_where = "";
|
||||
$catalog_join = "LEFT JOIN `catalog` ON `catalog`.`id` = `song`.`catalog`";
|
||||
if ($catalog) {
|
||||
$catalog_where .= " AND `catalog`.`id` = '$catalog'";
|
||||
$catalog_where .= " AND `catalog`.`id` = '" . $catalog . "'";
|
||||
}
|
||||
if (AmpConfig::get('catalog_disable')) {
|
||||
$catalog_where .= " AND `catalog`.`enabled` = '1'";
|
||||
|
@ -190,14 +286,38 @@ class Artist extends database_object
|
|||
}
|
||||
$sql_group = "COALESCE($sql_group_type, `album`.`id`)";
|
||||
|
||||
$sql = "SELECT `album`.`id` FROM album LEFT JOIN `song` ON `song`.`album`=`album`.`id` $catalog_join " .
|
||||
"WHERE `song`.`artist`='$this->id' $catalog_where GROUP BY $sql_group ORDER BY $sql_sort";
|
||||
$sql = "SELECT `album`.`id`, `album`.`release_type` FROM album LEFT JOIN `song` ON `song`.`album`=`album`.`id` $catalog_join " .
|
||||
"WHERE (`song`.`artist`='$this->id' OR `album`.`album_artist`='$this->id') $catalog_where GROUP BY $sql_group ORDER BY $sql_sort";
|
||||
|
||||
debug_event("Artist", "$sql", "6");
|
||||
$db_results = Dba::read($sql);
|
||||
|
||||
while ($r = Dba::fetch_assoc($db_results)) {
|
||||
$results[] = $r['id'];
|
||||
if ($group_release_type) {
|
||||
// We assume undefined release type is album
|
||||
$rtype = $r['release_type'] ?: 'album';
|
||||
if (!isset($results[$rtype])) {
|
||||
$results[$rtype] = array();
|
||||
}
|
||||
$results[$rtype][] = $r['id'];
|
||||
|
||||
$sort = AmpConfig::get('album_release_type_sort');
|
||||
if ($sort) {
|
||||
$results_sort = array();
|
||||
$asort = explode(',', $sort);
|
||||
|
||||
foreach ($asort as $rtype) {
|
||||
if (array_key_exists($rtype, $results)) {
|
||||
$results_sort[$rtype] = $results[$rtype];
|
||||
unset($results[$rtype]);
|
||||
}
|
||||
}
|
||||
|
||||
$results = array_merge($results_sort, $results);
|
||||
}
|
||||
} else {
|
||||
$results[] = $r['id'];
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
|
@ -207,6 +327,7 @@ class Artist extends database_object
|
|||
/**
|
||||
* get_songs
|
||||
* gets the songs for this artist
|
||||
* @return int[]
|
||||
*/
|
||||
public function get_songs()
|
||||
{
|
||||
|
@ -214,12 +335,12 @@ class Artist extends database_object
|
|||
if (AmpConfig::get('catalog_disable')) {
|
||||
$sql .= "LEFT JOIN `catalog` ON `catalog`.`id` = `song`.`catalog` ";
|
||||
}
|
||||
$sql .= "WHERE `song`.`artist`='" . Dba::escape($this->id) . "' ";
|
||||
$sql .= "WHERE `song`.`artist` = ? ";
|
||||
if (AmpConfig::get('catalog_disable')) {
|
||||
$sql .= "AND `catalog`.`enabled` = '1' ";
|
||||
}
|
||||
$sql .= "ORDER BY album, track";
|
||||
$db_results = Dba::read($sql);
|
||||
$sql .= "ORDER BY `song`.`album`, `song`.`track`";
|
||||
$db_results = Dba::read($sql, array($this->id));
|
||||
|
||||
$results = array();
|
||||
while ($r = Dba::fetch_assoc($db_results)) {
|
||||
|
@ -233,6 +354,7 @@ class Artist extends database_object
|
|||
/**
|
||||
* get_random_songs
|
||||
* Gets the songs from this artist in a random order
|
||||
* @return int[]
|
||||
*/
|
||||
public function get_random_songs()
|
||||
{
|
||||
|
@ -242,12 +364,12 @@ class Artist extends database_object
|
|||
if (AmpConfig::get('catalog_disable')) {
|
||||
$sql .= "LEFT JOIN `catalog` ON `catalog`.`id` = `song`.`catalog` ";
|
||||
}
|
||||
$sql .= "WHERE `song`.`artist`='$this->id' ";
|
||||
$sql .= "WHERE `song`.`artist` = ? ";
|
||||
if (AmpConfig::get('catalog_disable')) {
|
||||
$sql .= "AND `catalog`.`enabled` = '1' ";
|
||||
}
|
||||
$sql .= "ORDER BY RAND()";
|
||||
$db_results = Dba::read($sql);
|
||||
$db_results = Dba::read($sql, array($this->id));
|
||||
|
||||
while ($r = Dba::fetch_assoc($db_results)) {
|
||||
$results[] = $r['id'];
|
||||
|
@ -260,15 +382,17 @@ class Artist extends database_object
|
|||
/**
|
||||
* _get_extra info
|
||||
* This returns the extra information for the artist, this means totals etc
|
||||
* @param int $catalog
|
||||
* @return array
|
||||
*/
|
||||
private function _get_extra_info($catalog=FALSE)
|
||||
private function _get_extra_info($catalog=0, $limit_threshold ='')
|
||||
{
|
||||
// Try to find it in the cache and save ourselves the trouble
|
||||
if (parent::is_cached('artist_extra',$this->id) ) {
|
||||
$row = parent::get_from_cache('artist_extra',$this->id);
|
||||
} else {
|
||||
$uid = Dba::escape($this->id);
|
||||
$sql = "SELECT `song`.`artist`,COUNT(`song`.`id`) AS `song_count`, COUNT(DISTINCT `song`.`album`) AS `album_count`, SUM(`song`.`time`) AS `time` FROM `song` LEFT JOIN `catalog` ON `catalog`.`id` = `song`.`catalog` " .
|
||||
$sql = "SELECT `song`.`artist`,COUNT(DISTINCT `song`.`id`) AS `song_count`, COUNT(DISTINCT `song`.`album`) AS `album_count`, SUM(`song`.`time`) AS `time`, `song`.`catalog` as `catalog_id` FROM `song` LEFT JOIN `catalog` ON `catalog`.`id` = `song`.`catalog` " .
|
||||
"WHERE `song`.`artist`='$uid' ";
|
||||
if ($catalog) {
|
||||
$sql .= "AND (`song`.`catalog` = '$catalog') ";
|
||||
|
@ -282,7 +406,7 @@ class Artist extends database_object
|
|||
$db_results = Dba::read($sql);
|
||||
$row = Dba::fetch_assoc($db_results);
|
||||
if (AmpConfig::get('show_played_times')) {
|
||||
$row['object_cnt'] = Stats::get_object_count('artist', $row['artist']);
|
||||
$row['object_cnt'] = Stats::get_object_count('artist', $row['artist'], $limit_threshold);
|
||||
}
|
||||
parent::add_to_cache('artist_extra',$row['artist'],$row);
|
||||
}
|
||||
|
@ -291,6 +415,7 @@ class Artist extends database_object
|
|||
$this->songs = $row['song_count'];
|
||||
$this->albums = $row['album_count'];
|
||||
$this->time = $row['time'];
|
||||
$this->catalog_id = $row['catalog_id'];
|
||||
|
||||
return $row;
|
||||
|
||||
|
@ -302,48 +427,225 @@ class Artist extends database_object
|
|||
* information and reformats the relevent values
|
||||
* so they can be displayed in a table for example
|
||||
* it changes the title into a full link.
|
||||
* @return boolean
|
||||
*/
|
||||
public function format()
|
||||
public function format($details = true, $limit_threshold = '')
|
||||
{
|
||||
/* Combine prefix and name, trim then add ... if needed */
|
||||
$name = trim($this->prefix . " " . $this->name);
|
||||
$this->f_name = $name;
|
||||
$this->f_full_name = trim(trim($this->prefix) . ' ' . trim($this->name));
|
||||
|
||||
// If this is a fake object, we're done here
|
||||
if ($this->_fake) { return true; }
|
||||
// If this is a memory-only object, we're done here
|
||||
if (!$this->id) { return true; }
|
||||
|
||||
if ($this->catalog_id) {
|
||||
$this->f_link = AmpConfig::get('web_path') . '/artists.php?action=show&catalog=' . $this->catalog_id . '&artist=' . $this->id;
|
||||
$this->f_name_link = "<a href=\"" . $this->f_link . "\" title=\"" . $this->f_full_name . "\">" . $name . "</a>";
|
||||
$this->link = AmpConfig::get('web_path') . '/artists.php?action=show&catalog=' . $this->catalog_id . '&artist=' . $this->id;
|
||||
$this->f_link = "<a href=\"" . $this->link . "\" title=\"" . $this->f_full_name . "\">" . $name . "</a>";
|
||||
} else {
|
||||
$this->f_link = AmpConfig::get('web_path') . '/artists.php?action=show&artist=' . $this->id;
|
||||
$this->f_name_link = "<a href=\"" . $this->f_link . "\" title=\"" . $this->f_full_name . "\">" . $name . "</a>";
|
||||
$this->link = AmpConfig::get('web_path') . '/artists.php?action=show&artist=' . $this->id;
|
||||
$this->f_link = "<a href=\"" . $this->link . "\" title=\"" . $this->f_full_name . "\">" . $name . "</a>";
|
||||
}
|
||||
// Get the counts
|
||||
$extra_info = $this->_get_extra_info($this->catalog_id);
|
||||
|
||||
//Format the new time thingy that we just got
|
||||
$min = sprintf("%02d",(floor($extra_info['time']/60)%60));
|
||||
if ($details) {
|
||||
// Get the counts
|
||||
$extra_info = $this->_get_extra_info($this->catalog_id, $limit_threshold);
|
||||
|
||||
$sec = sprintf("%02d",($extra_info['time']%60));
|
||||
$hours = floor($extra_info['time']/3600);
|
||||
//Format the new time thingy that we just got
|
||||
$min = sprintf("%02d",(floor($extra_info['time']/60)%60));
|
||||
|
||||
$this->f_time = ltrim($hours . ':' . $min . ':' . $sec,'0:');
|
||||
$sec = sprintf("%02d",($extra_info['time']%60));
|
||||
$hours = floor($extra_info['time']/3600);
|
||||
|
||||
$this->tags = Tag::get_top_tags('artist', $this->id);
|
||||
$this->f_tags = Tag::get_display($this->tags);
|
||||
$this->f_time = ltrim($hours . ':' . $min . ':' . $sec,'0:');
|
||||
|
||||
$this->object_cnt = $extra_info['object_cnt'];
|
||||
$this->tags = Tag::get_top_tags('artist', $this->id);
|
||||
$this->f_tags = Tag::get_display($this->tags, true, 'artist');
|
||||
|
||||
if (AmpConfig::get('label')) {
|
||||
$this->labels = Label::get_labels($this->id);
|
||||
$this->f_labels = Label::get_display($this->labels, true);
|
||||
}
|
||||
|
||||
$this->object_cnt = $extra_info['object_cnt'];
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} // format
|
||||
|
||||
/**
|
||||
* Get item keywords for metadata searches.
|
||||
* @return array
|
||||
*/
|
||||
public function get_keywords()
|
||||
{
|
||||
$keywords = array();
|
||||
$keywords['mb_artistid'] = array('important' => false,
|
||||
'label' => T_('Artist MusicBrainzID'),
|
||||
'value' => $this->mbid);
|
||||
$keywords['artist'] = array('important' => true,
|
||||
'label' => T_('Artist'),
|
||||
'value' => $this->f_full_name);
|
||||
|
||||
return $keywords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get item fullname.
|
||||
* @return string
|
||||
*/
|
||||
public function get_fullname()
|
||||
{
|
||||
return $this->f_full_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parent item description.
|
||||
* @return array|null
|
||||
*/
|
||||
public function get_parent()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get item childrens.
|
||||
* @return array
|
||||
*/
|
||||
public function get_childrens()
|
||||
{
|
||||
$medias = array();
|
||||
$albums = $this->get_albums();
|
||||
foreach ($albums as $album_id) {
|
||||
$medias[] = array(
|
||||
'object_type' => 'album',
|
||||
'object_id' => $album_id
|
||||
);
|
||||
}
|
||||
return array('album' => $medias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for item childrens.
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
public function search_childrens($name)
|
||||
{
|
||||
$search['type'] = "album";
|
||||
$search['rule_0_input'] = $name;
|
||||
$search['rule_0_operator'] = 4;
|
||||
$search['rule_0'] = "title";
|
||||
$search['rule_1_input'] = $this->name;
|
||||
$search['rule_1_operator'] = 4;
|
||||
$search['rule_1'] = "artist";
|
||||
$albums = Search::run($search);
|
||||
|
||||
$childrens = array();
|
||||
foreach ($albums as $album) {
|
||||
$childrens[] = array(
|
||||
'object_type' => 'album',
|
||||
'object_id' => $album
|
||||
);
|
||||
}
|
||||
return $childrens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all childrens and sub-childrens medias.
|
||||
* @param string $filter_type
|
||||
* @return array
|
||||
*/
|
||||
public function get_medias($filter_type = null)
|
||||
{
|
||||
$medias = array();
|
||||
if (!$filter_type || $filter_type == 'song') {
|
||||
$songs = $this->get_songs();
|
||||
foreach ($songs as $song_id) {
|
||||
$medias[] = array(
|
||||
'object_type' => 'song',
|
||||
'object_id' => $song_id
|
||||
);
|
||||
}
|
||||
}
|
||||
return $medias;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_catalogs
|
||||
*
|
||||
* Get all catalog ids related to this item.
|
||||
* @return int[]
|
||||
*/
|
||||
public function get_catalogs()
|
||||
{
|
||||
return array($this->catalog_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get item's owner.
|
||||
* @return int|null
|
||||
*/
|
||||
public function get_user_owner()
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default art kind for this item.
|
||||
* @return string
|
||||
*/
|
||||
public function get_default_art_kind()
|
||||
{
|
||||
return 'default';
|
||||
}
|
||||
|
||||
public function get_description()
|
||||
{
|
||||
return $this->summary;
|
||||
}
|
||||
|
||||
public function display_art($thumb = 2)
|
||||
{
|
||||
$id = null;
|
||||
$type = null;
|
||||
|
||||
if (Art::has_db($this->id, 'artist')) {
|
||||
$id = $this->id;
|
||||
$type = 'artist';
|
||||
}
|
||||
|
||||
if ($id !== null && $type !== null) {
|
||||
Art::display($type, $id, $this->get_fullname(), $thumb, $this->link);
|
||||
}
|
||||
}
|
||||
|
||||
public function can_edit($user = null)
|
||||
{
|
||||
if (!$user) {
|
||||
$user = $GLOBALS['user']->id;
|
||||
}
|
||||
|
||||
if (!$user)
|
||||
return false;
|
||||
|
||||
if (AmpConfig::get('upload_allow_edit')) {
|
||||
if ($this->user !== null && $user == $this->user)
|
||||
return true;
|
||||
}
|
||||
|
||||
return Access::check('interface', 50, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* check
|
||||
*
|
||||
* Checks for an existing artist; if none exists, insert one.
|
||||
* @param string $name
|
||||
* @param string $mbid
|
||||
* @param boolean $readonly
|
||||
* @return int|null
|
||||
*/
|
||||
public static function check($name, $mbid = null, $readonly = false)
|
||||
{
|
||||
|
@ -429,27 +731,37 @@ class Artist extends database_object
|
|||
/**
|
||||
* update
|
||||
* This takes a key'd array of data and updates the current artist
|
||||
* @param array $data
|
||||
* @return int
|
||||
*/
|
||||
public function update($data)
|
||||
public function update(array $data)
|
||||
{
|
||||
// Save our current ID
|
||||
$name = isset($data['name']) ? $data['name'] : $this->name;
|
||||
$mbid = isset($data['mbid']) ? $data['mbid'] : $this->mbid;
|
||||
$summary = isset($data['summary']) ? $data['summary'] : $this->summary;
|
||||
$placeformed = isset($data['placeformed']) ? $data['placeformed'] : $this->placeformed;
|
||||
$yearformed = isset($data['yearformed']) ? $data['yearformed'] : $this->yearformed;
|
||||
|
||||
$current_id = $this->id;
|
||||
|
||||
// Check if name is different than current name
|
||||
if ($this->name != $data['name']) {
|
||||
$artist_id = self::check($data['name'], $this->mbid);
|
||||
if ($this->name != $name) {
|
||||
$artist_id = self::check($name, $mbid, true);
|
||||
|
||||
$updated = false;
|
||||
$songs = array();
|
||||
|
||||
// If it's changed we need to update
|
||||
if ($artist_id != $this->id) {
|
||||
if ($artist_id != null && $artist_id != $this->id) {
|
||||
$songs = $this->get_songs();
|
||||
foreach ($songs as $song_id) {
|
||||
Song::update_artist($artist_id,$song_id);
|
||||
}
|
||||
$updated = true;
|
||||
$current_id = $artist_id;
|
||||
Stats::migrate('artist', $this->id, $artist_id);
|
||||
Art::migrate('artist', $this->id, $artist_id);
|
||||
self::gc();
|
||||
} // end if it changed
|
||||
|
||||
|
@ -461,24 +773,41 @@ class Artist extends database_object
|
|||
Rating::gc();
|
||||
Userflag::gc();
|
||||
} // if updated
|
||||
} else if ($this->mbid != $data['mbid']) {
|
||||
} else if ($this->mbid != $mbid) {
|
||||
$sql = 'UPDATE `artist` SET `mbid` = ? WHERE `id` = ?';
|
||||
Dba::write($sql, array($data['mbid'], $current_id));
|
||||
Dba::write($sql, array($mbid, $current_id));
|
||||
}
|
||||
|
||||
// Update artist name (if we don't want to use the MusicBrainz name)
|
||||
$trimmed = Catalog::trim_prefix(trim($data['name']));
|
||||
$trimmed = Catalog::trim_prefix(trim($name));
|
||||
$name = $trimmed['string'];
|
||||
if ($name != '' && $name != $this->name) {
|
||||
$sql = 'UPDATE `artist` SET `name` = ? WHERE `id` = ?';
|
||||
Dba::write($sql, array($name, $current_id));
|
||||
}
|
||||
|
||||
$this->update_artist_info($summary, $placeformed, $yearformed);
|
||||
|
||||
$this->name = $name;
|
||||
$this->mbid = $mbid;
|
||||
|
||||
$override_childs = false;
|
||||
if ($data['apply_childs'] == 'checked') {
|
||||
if ($data['overwrite_childs'] == 'checked') {
|
||||
$override_childs = true;
|
||||
}
|
||||
$this->update_tags($data['edit_tags'], $override_childs, $current_id);
|
||||
|
||||
$add_to_childs = false;
|
||||
if ($data['add_to_childs'] == 'checked') {
|
||||
$add_to_childs = true;
|
||||
}
|
||||
|
||||
if (isset($data['edit_tags'])) {
|
||||
$this->update_tags($data['edit_tags'], $override_childs, $add_to_childs, $current_id, true);
|
||||
}
|
||||
|
||||
if (AmpConfig::get('label') && isset($data['edit_labels'])) {
|
||||
Label::update_label_list($data['edit_labels'], $this->id, true);
|
||||
}
|
||||
|
||||
return $current_id;
|
||||
|
||||
|
@ -488,28 +817,82 @@ class Artist extends database_object
|
|||
* update_tags
|
||||
*
|
||||
* Update tags of artists and/or albums
|
||||
* @param string $tags_comma
|
||||
* @param boolean $override_childs
|
||||
* @param int|null $current_id
|
||||
*/
|
||||
public function update_tags($tags_comma, $override_childs, $current_id = null)
|
||||
public function update_tags($tags_comma, $override_childs, $add_to_childs, $current_id = null, $force_update = false)
|
||||
{
|
||||
if ($current_id == null) {
|
||||
$current_id = $this->id;
|
||||
}
|
||||
|
||||
Tag::update_tag_list($tags_comma, 'artist', $current_id);
|
||||
Tag::update_tag_list($tags_comma, 'artist', $current_id, $force_update ? true : $override_childs);
|
||||
|
||||
if ($override_childs) {
|
||||
if ($override_childs || $add_to_childs) {
|
||||
$albums = $this->get_albums(null, true);
|
||||
foreach ($albums as $album_id) {
|
||||
$album = new Album($album_id);
|
||||
$album->update_tags($tags_comma, $override_childs);
|
||||
$album->update_tags($tags_comma, $override_childs, $add_to_childs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update artist information.
|
||||
* @param string $summary
|
||||
* @param string $placeformed
|
||||
* @param int $yearformed
|
||||
* @return boolean
|
||||
*/
|
||||
public function update_artist_info($summary, $placeformed, $yearformed)
|
||||
{
|
||||
$sql = "UPDATE `artist` SET `summary` = ?, `placeformed` = ?, `yearformed` = ?, `last_update` = ? WHERE `id` = ?";
|
||||
return Dba::write($sql, array($summary, $placeformed, $yearformed, time(), $this->id));
|
||||
$sqlret = Dba::write($sql, array($summary, $placeformed, $yearformed, time(), $this->id));
|
||||
|
||||
$this->summary = $summary;
|
||||
$this->placeformed = $placeformed;
|
||||
$this->yearformed = $yearformed;
|
||||
|
||||
return $sqlret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update artist associated user.
|
||||
* @param int $user
|
||||
* @return boolean
|
||||
*/
|
||||
public function update_artist_user($user)
|
||||
{
|
||||
$sql = "UPDATE `artist` SET `user` = ? WHERE `id` = ?";
|
||||
return Dba::write($sql, array($user, $this->id));
|
||||
}
|
||||
|
||||
public function remove_from_disk()
|
||||
{
|
||||
$deleted = true;
|
||||
$album_ids = $this->get_albums();
|
||||
foreach ($album_ids as $id) {
|
||||
$album = new Album($id);
|
||||
$deleted = $album->remove_from_disk();
|
||||
if (!$deleted) {
|
||||
debug_event('artist', 'Error when deleting the album `' . $id .'`.', 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($deleted) {
|
||||
$sql = "DELETE FROM `artist` WHERE `id` = ?";
|
||||
$deleted = Dba::write($sql, array($this->id));
|
||||
if ($deleted) {
|
||||
Art::gc('artist', $this->id);
|
||||
Userflag::gc('artist', $this->id);
|
||||
Rating::gc('artist', $this->id);
|
||||
Shoutbox::gc('artist', $this->id);
|
||||
}
|
||||
}
|
||||
|
||||
return $deleted;
|
||||
}
|
||||
|
||||
} // end of artist class
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -33,8 +33,10 @@ class Artist_Event
|
|||
/**
|
||||
* get_upcoming_events
|
||||
* Returns a list of upcoming events
|
||||
* @param Artist $artist
|
||||
* @return SimpleXMLElement|boolean
|
||||
*/
|
||||
public static function get_upcoming_events($artist)
|
||||
public static function get_upcoming_events(Artist $artist)
|
||||
{
|
||||
if (isset($artist->mbid)) {
|
||||
$query = 'mbid=' . rawurlencode($artist->mbid);
|
||||
|
@ -59,8 +61,10 @@ class Artist_Event
|
|||
/**
|
||||
* get_past_events
|
||||
* Returns a list of past events
|
||||
* @param Artist $artist
|
||||
* @return SimpleXMLElement|boolean
|
||||
*/
|
||||
public static function get_past_events($artist)
|
||||
public static function get_past_events(Artist $artist)
|
||||
{
|
||||
if (isset($artist->mbid)) {
|
||||
$query = 'mbid=' . rawurlencode($artist->mbid);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -44,6 +44,8 @@ class Auth
|
|||
* This is called when you want to log out and nuke your session.
|
||||
* This is the function used for the Ajax logouts, if no id is passed
|
||||
* it tries to find one from the session,
|
||||
* @param string $key
|
||||
* @param boolean $relogin
|
||||
*/
|
||||
public static function logout($key='', $relogin = true)
|
||||
{
|
||||
|
@ -82,6 +84,10 @@ class Auth
|
|||
*
|
||||
* This takes a username and password and then returns the results
|
||||
* based on what happens when we try to do the auth.
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param boolean $allow_ui
|
||||
* @return array
|
||||
*/
|
||||
public static function login($username, $password, $allow_ui = false)
|
||||
{
|
||||
|
@ -104,6 +110,8 @@ class Auth
|
|||
* login_step2
|
||||
*
|
||||
* This process authenticate step2 for an auth module
|
||||
* @param string $auth_mod
|
||||
* @return array
|
||||
*/
|
||||
public static function login_step2($auth_mod)
|
||||
{
|
||||
|
@ -122,6 +130,9 @@ class Auth
|
|||
* mysql_auth
|
||||
*
|
||||
* This is the core function of our built-in authentication.
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return array
|
||||
*/
|
||||
private static function mysql_auth($username, $password)
|
||||
{
|
||||
|
@ -168,6 +179,9 @@ class Auth
|
|||
*
|
||||
* Check to make sure the pam_auth function is implemented (module is
|
||||
* installed), then check the credentials.
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return array
|
||||
*/
|
||||
private static function pam_auth($username, $password)
|
||||
{
|
||||
|
@ -197,6 +211,9 @@ class Auth
|
|||
*
|
||||
* Calls an external program compatible with mod_authnz_external
|
||||
* such as pwauth.
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return array
|
||||
*/
|
||||
private static function external_auth($username, $password)
|
||||
{
|
||||
|
@ -221,7 +238,7 @@ class Auth
|
|||
fclose($pipes[0]);
|
||||
fclose($pipes[1]);
|
||||
if ($stderr = fread($pipes[2], 8192)) {
|
||||
debug_event('external_auth', $stderr, 5);
|
||||
debug_event('external_auth', "fread error: " . $stderr, 5);
|
||||
}
|
||||
fclose($pipes[2]);
|
||||
} else {
|
||||
|
@ -257,6 +274,9 @@ class Auth
|
|||
* the DN fetched from the LDAP directory"
|
||||
* * require-attribute "an attribute fetched from the LDAP
|
||||
* directory matches the given value"
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return array
|
||||
*/
|
||||
private static function ldap_auth($username, $password)
|
||||
{
|
||||
|
@ -285,6 +305,13 @@ class Auth
|
|||
return $results;
|
||||
}
|
||||
|
||||
if (strpos($ldap_filter, "%v") >= 0) {
|
||||
$ldap_filter = str_replace("%v", $username, $ldap_filter);
|
||||
} else {
|
||||
// This to support previous configuration where only the fieldname was set
|
||||
$ldap_filter = "($ldap_filter=$username)";
|
||||
}
|
||||
|
||||
$ldap_name_field = AmpConfig::get('ldap_name_field');
|
||||
$ldap_email_field = AmpConfig::get('ldap_email_field');
|
||||
|
||||
|
@ -300,7 +327,9 @@ class Auth
|
|||
return $results;
|
||||
} // If bind fails
|
||||
|
||||
$sr = ldap_search($ldap_link, $ldap_dn, "(&(objectclass=$ldap_class)($ldap_filter=$username))");
|
||||
$searchstr = "(&(objectclass=$ldap_class)$ldap_filter)";
|
||||
debug_event('ldap_auth', 'ldap_search: ' . $searchstr, 5);
|
||||
$sr = ldap_search($ldap_link, $ldap_dn, $searchstr);
|
||||
$info = ldap_get_entries($ldap_link, $sr);
|
||||
|
||||
if ($info["count"] == 1) {
|
||||
|
@ -367,6 +396,9 @@ class Auth
|
|||
* http_auth
|
||||
* This auth method relies on HTTP auth from the webserver
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return array
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
private static function http_auth($username, $password)
|
||||
|
@ -390,6 +422,9 @@ class Auth
|
|||
* openid_auth
|
||||
* Authenticate user with OpenID
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return array
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
private static function openid_auth($username, $password)
|
||||
|
@ -468,6 +503,7 @@ class Auth
|
|||
/**
|
||||
* openid_auth_2
|
||||
* Authenticate user with OpenID, step 2
|
||||
* @return array
|
||||
*/
|
||||
private static function openid_auth_2()
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -38,6 +38,10 @@ class AutoUpdate
|
|||
// static class
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current version is a development version.
|
||||
* @return boolean
|
||||
*/
|
||||
protected static function is_develop()
|
||||
{
|
||||
$version = AmpConfig::get('version');
|
||||
|
@ -46,39 +50,56 @@ class AutoUpdate
|
|||
return ($vspart[count($vspart) - 1] == 'develop');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current version is a git repository.
|
||||
* @return boolean
|
||||
*/
|
||||
protected static function is_git_repository()
|
||||
{
|
||||
return is_dir(AmpConfig::get('prefix') . '/.git');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if branch develop exists in git repository.
|
||||
* @return boolean
|
||||
*/
|
||||
protected static function is_branch_develop_exists()
|
||||
{
|
||||
return is_readable(AmpConfig::get('prefix') . '/.git/refs/heads/develop');
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a GitHub request.
|
||||
* @param string $action
|
||||
* @return string|null
|
||||
*/
|
||||
public static function github_request($action)
|
||||
{
|
||||
try {
|
||||
// https is mandatory
|
||||
$url = "https://api.github.com/repos/ampache/ampache" . $action;
|
||||
$request = Requests::get($url);
|
||||
$request = Requests::get($url, array(), Core::requests_options());
|
||||
|
||||
// Not connected / API rate limit exceeded: just ignore, it will pass next time
|
||||
if ($request->status_code != 200) {
|
||||
debug_event('autoupdate', 'Github API request ' . $url . ' failed with http code ' . $request->status_code, '1');
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
return json_decode($request->body);
|
||||
} catch (Exception $e) {
|
||||
debug_event('autoupdate', 'Request error: ' . $e->getMessage(), '1');
|
||||
return "";
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if last github check expired.
|
||||
* @return boolean
|
||||
*/
|
||||
protected static function lastcheck_expired()
|
||||
{
|
||||
$lastcheck = AmpConfig::get('autoupdate_lastcheck');
|
||||
if (!$lastcheck) {
|
||||
User::rebuild_all_preferences();
|
||||
Preference::update('autoupdate_lastcheck', $GLOBALS['user']->id, '1');
|
||||
AmpConfig::set('autoupdate_lastcheck', '1', true);
|
||||
}
|
||||
|
@ -86,11 +107,21 @@ class AutoUpdate
|
|||
return ((time() - (3600 * 3)) > $lastcheck);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get latest available version from GitHub.
|
||||
* @param boolean $force
|
||||
* @return string
|
||||
*/
|
||||
public static function get_latest_version($force = false)
|
||||
{
|
||||
$lastversion = '';
|
||||
// Forced or last check expired, check latest version from Github
|
||||
if ($force || (self::lastcheck_expired() && AmpConfig::get('autoupdate'))) {
|
||||
// Always update last check time to avoid infinite check on permanent errors (proxy, firewall, ...)
|
||||
$time = time();
|
||||
Preference::update('autoupdate_lastcheck', $GLOBALS['user']->id, $time);
|
||||
AmpConfig::set('autoupdate_lastcheck', $time, true);
|
||||
|
||||
// Development version, get latest commit on develop branch
|
||||
if (self::is_develop()) {
|
||||
$commits = self::github_request('/commits/develop');
|
||||
|
@ -98,9 +129,6 @@ class AutoUpdate
|
|||
$lastversion = $commits->sha;
|
||||
Preference::update('autoupdate_lastversion', $GLOBALS['user']->id, $lastversion);
|
||||
AmpConfig::set('autoupdate_lastversion', $lastversion, true);
|
||||
$time = time();
|
||||
Preference::update('autoupdate_lastcheck', $GLOBALS['user']->id, $time);
|
||||
AmpConfig::set('autoupdate_lastcheck', $time, true);
|
||||
$available = self::is_update_available(true);
|
||||
Preference::update('autoupdate_lastversion_new', $GLOBALS['user']->id, $available);
|
||||
AmpConfig::set('autoupdate_lastversion_new', $available, true);
|
||||
|
@ -113,9 +141,6 @@ class AutoUpdate
|
|||
$lastversion = $tags[0]->name;
|
||||
Preference::update('autoupdate_lastversion', $GLOBALS['user']->id, $lastversion);
|
||||
AmpConfig::set('autoupdate_lastversion', $lastversion, true);
|
||||
$time = time();
|
||||
Preference::update('autoupdate_lastcheck', $GLOBALS['user']->id, $time);
|
||||
AmpConfig::set('autoupdate_lastcheck', $time, true);
|
||||
$available = self::is_update_available(true);
|
||||
Preference::update('autoupdate_lastversion_new', $GLOBALS['user']->id, $available);
|
||||
AmpConfig::set('autoupdate_lastversion_new', $available, true);
|
||||
|
@ -130,6 +155,10 @@ class AutoUpdate
|
|||
return $lastversion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current local version.
|
||||
* @return string
|
||||
*/
|
||||
public static function get_current_version()
|
||||
{
|
||||
if (self::is_develop()) {
|
||||
|
@ -139,15 +168,24 @@ class AutoUpdate
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current local git commit.
|
||||
* @return string
|
||||
*/
|
||||
public static function get_current_commit()
|
||||
{
|
||||
if (self::is_branch_develop_exists()) {
|
||||
return trim(file_get_contents(AmpConfig::get('prefix') . '/.git/refs/heads/develop'));
|
||||
}
|
||||
|
||||
return false;
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an update is available.
|
||||
* @param boolean $force
|
||||
* @return boolean
|
||||
*/
|
||||
public static function is_update_available($force = false)
|
||||
{
|
||||
if (!$force && (!self::lastcheck_expired() || !AmpConfig::get('autoupdate'))) {
|
||||
|
@ -183,6 +221,9 @@ class AutoUpdate
|
|||
return $available;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display new version information and update link if possible.
|
||||
*/
|
||||
public static function show_new_version()
|
||||
{
|
||||
echo '<div>';
|
||||
|
@ -191,6 +232,23 @@ class AutoUpdate
|
|||
|
||||
echo T_('See') . ' <a href="https://github.com/ampache/ampache/' . (self::is_develop() ? 'compare/' . self::get_current_version() . '...' . self::get_latest_version() : 'blob/master/docs/CHANGELOG.md') . '" target="_blank">' . T_('changes') . '</a> ';
|
||||
echo T_('or') . ' <a href="https://github.com/ampache/ampache/archive/' . (self::is_develop() ? 'develop.zip' : self::get_latest_version() . '.zip') . '" target="_blank"><b>' . T_('download') . '</b></a>.';
|
||||
if (self::is_git_repository()) {
|
||||
echo ' | <a rel="nohtml" href="' . AmpConfig::get('web_path') . '/update.php?type=sources&action=update">.:: Update ::.</a>';
|
||||
}
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Update local git repository.
|
||||
*/
|
||||
public static function update_files()
|
||||
{
|
||||
echo T_('Updating Ampache sources with `git pull` ...') . '<br />';
|
||||
ob_flush();
|
||||
chdir(AmpConfig::get('prefix'));
|
||||
exec('git pull https://github.com/ampache/ampache.git');
|
||||
echo T_('Done') . '<br />';
|
||||
ob_flush();
|
||||
self::get_latest_version(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -20,22 +20,61 @@
|
|||
*
|
||||
*/
|
||||
|
||||
class Broadcast extends database_object
|
||||
class Broadcast extends database_object implements library_item
|
||||
{
|
||||
/**
|
||||
* @var int $id
|
||||
*/
|
||||
public $id;
|
||||
/**
|
||||
* @var boolean $started
|
||||
*/
|
||||
public $started;
|
||||
/**
|
||||
* @var int $listeners
|
||||
*/
|
||||
public $listeners;
|
||||
/**
|
||||
* @var int $song
|
||||
*/
|
||||
public $song;
|
||||
/**
|
||||
* @var int $song_position
|
||||
*/
|
||||
public $song_position;
|
||||
/**
|
||||
* @var string $name
|
||||
*/
|
||||
public $name;
|
||||
/**
|
||||
* @var int $user
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* @var array $tags
|
||||
*/
|
||||
public $tags;
|
||||
/**
|
||||
* @var string $f_name
|
||||
*/
|
||||
public $f_name;
|
||||
/**
|
||||
* @var string $f_link
|
||||
*/
|
||||
public $f_link;
|
||||
/**
|
||||
* @var string $f_tags
|
||||
*/
|
||||
public $f_tags;
|
||||
/**
|
||||
* @var boolean $is_private
|
||||
*/
|
||||
public $is_private;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param int $id
|
||||
*/
|
||||
public function __construct($id=0)
|
||||
{
|
||||
|
@ -52,6 +91,11 @@ class Broadcast extends database_object
|
|||
return true;
|
||||
} //constructor
|
||||
|
||||
/**
|
||||
* Update broadcast state.
|
||||
* @param boolean $started
|
||||
* @param string $key
|
||||
*/
|
||||
public function update_state($started, $key='')
|
||||
{
|
||||
$sql = "UPDATE `broadcast` SET `started` = ?, `key` = ?, `song` = '0', `listeners` = '0' WHERE `id` = ?";
|
||||
|
@ -60,6 +104,10 @@ class Broadcast extends database_object
|
|||
$this->started = $started;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update broadcast listeners.
|
||||
* @param int $listeners
|
||||
*/
|
||||
public function update_listeners($listeners)
|
||||
{
|
||||
$sql = "UPDATE `broadcast` SET `listeners` = ? " .
|
||||
|
@ -68,6 +116,10 @@ class Broadcast extends database_object
|
|||
$this->listeners = $listeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update broadcast current song.
|
||||
* @param int $song_id
|
||||
*/
|
||||
public function update_song($song_id)
|
||||
{
|
||||
$sql = "UPDATE `broadcast` SET `song` = ? " .
|
||||
|
@ -77,12 +129,22 @@ class Broadcast extends database_object
|
|||
$this->song_position = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the broadcast.
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$sql = "DELETE FROM `broadcast` WHERE `id` = ?";
|
||||
return Dba::write($sql, array($this->id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a broadcast
|
||||
* @param string $name
|
||||
* @param string $description
|
||||
* @return int
|
||||
*/
|
||||
public static function create($name, $description='')
|
||||
{
|
||||
if (!empty($name)) {
|
||||
|
@ -95,26 +157,144 @@ class Broadcast extends database_object
|
|||
return 0;
|
||||
}
|
||||
|
||||
public function update($data)
|
||||
/**
|
||||
* Update a broadcast from data array.
|
||||
* @param array $data
|
||||
* @return int
|
||||
*/
|
||||
public function update(array $data)
|
||||
{
|
||||
if (isset($data['edit_tags'])) {
|
||||
Tag::update_tag_list($data['edit_tags'], 'broadcast', $this->id);
|
||||
Tag::update_tag_list($data['edit_tags'], 'broadcast', $this->id, true);
|
||||
}
|
||||
|
||||
$sql = "UPDATE `broadcast` SET `name` = ?, `description` = ?, `is_private` = ? " .
|
||||
"WHERE `id` = ?";
|
||||
$params = array($data['name'], $data['description'], !empty($data['private']), $this->id);
|
||||
return Dba::write($sql, $params);
|
||||
Dba::write($sql, $params);
|
||||
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function format()
|
||||
public function format($details = true)
|
||||
{
|
||||
$this->f_name = $this->name;
|
||||
$this->f_link = '<a href="' . AmpConfig::get('web_path') . '/broadcast.php?id=' . $this->id . '">' . scrub_out($this->f_name) . '</a>';
|
||||
$this->tags = Tag::get_top_tags('broadcast', $this->id);
|
||||
$this->f_tags = Tag::get_display($this->tags);
|
||||
if ($details) {
|
||||
$this->tags = Tag::get_top_tags('broadcast', $this->id);
|
||||
$this->f_tags = Tag::get_display($this->tags, true, 'broadcast');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get item keywords for metadata searches.
|
||||
* @return array
|
||||
*/
|
||||
public function get_keywords()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get item fullname.
|
||||
* @return string
|
||||
*/
|
||||
public function get_fullname()
|
||||
{
|
||||
return $this->f_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parent item description.
|
||||
* @return array|null
|
||||
*/
|
||||
public function get_parent()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get item childrens.
|
||||
* @return array
|
||||
*/
|
||||
public function get_childrens()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for item childrens.
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
public function search_childrens($name)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all childrens and sub-childrens medias.
|
||||
* @param string $filter_type
|
||||
* @return array
|
||||
*/
|
||||
public function get_medias($filter_type = null)
|
||||
{
|
||||
// Not a media, shouldn't be that
|
||||
$medias = array();
|
||||
if (!$filter_type || $filter_type == 'broadcast') {
|
||||
$medias[] = array(
|
||||
'object_type' => 'broadcast',
|
||||
'object_id' => $this->id
|
||||
);
|
||||
}
|
||||
return $medias;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_catalogs
|
||||
*
|
||||
* Get all catalog ids related to this item.
|
||||
* @return int[]
|
||||
*/
|
||||
public function get_catalogs()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get item's owner.
|
||||
* @return int|null
|
||||
*/
|
||||
public function get_user_owner()
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default art kind for this item.
|
||||
* @return string
|
||||
*/
|
||||
public function get_default_art_kind()
|
||||
{
|
||||
return 'default';
|
||||
}
|
||||
|
||||
public function get_description()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function display_art($thumb = 2)
|
||||
{
|
||||
if (Art::has_db($this->id, 'broadcast')) {
|
||||
Art::display('broadcast', $this->id, $this->get_fullname(), $thumb, $this->link);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all broadcasts sql query.
|
||||
* @return string
|
||||
*/
|
||||
public static function get_broadcast_list_sql()
|
||||
{
|
||||
$sql = "SELECT `id` FROM `broadcast` WHERE `started` = '1' ";
|
||||
|
@ -122,6 +302,10 @@ class Broadcast extends database_object
|
|||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all broadcasts.
|
||||
* @return int[]
|
||||
*/
|
||||
public static function get_broadcast_list()
|
||||
{
|
||||
$sql = self::get_broadcast_list_sql();
|
||||
|
@ -135,12 +319,21 @@ class Broadcast extends database_object
|
|||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new broadcast key.
|
||||
* @return string
|
||||
*/
|
||||
public static function generate_key()
|
||||
{
|
||||
// Should be improved for security reasons!
|
||||
return md5(uniqid(rand(), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get broadcast from its key.
|
||||
* @param string $key
|
||||
* @return Broadcast|null
|
||||
*/
|
||||
public static function get_broadcast($key)
|
||||
{
|
||||
$sql = "SELECT `id` FROM `broadcast` WHERE `key` = ?";
|
||||
|
@ -153,16 +346,23 @@ class Broadcast extends database_object
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show action buttons.
|
||||
*/
|
||||
public function show_action_buttons()
|
||||
{
|
||||
if ($this->id) {
|
||||
if ($GLOBALS['user']->has_access('75')) {
|
||||
echo "<a id=\"edit_broadcast_ " . $this->id . "\" onclick=\"showEditDialog('broadcast_row', '" . $this->id . "', 'edit_broadcast_" . $this->id . "', '" . T_('Broadcast edit') . "', 'broadcast_row_', 'refresh_broadcast')\">" . UI::get_icon('edit', T_('Edit')) . "</a>";
|
||||
echo "<a id=\"edit_broadcast_ " . $this->id . "\" onclick=\"showEditDialog('broadcast_row', '" . $this->id . "', 'edit_broadcast_" . $this->id . "', '" . T_('Broadcast edit') . "', 'broadcast_row_')\">" . UI::get_icon('edit', T_('Edit')) . "</a>";
|
||||
echo " <a href=\"" . AmpConfig::get('web_path') . "/broadcast.php?action=show_delete&id=" . $this->id ."\">" . UI::get_icon('delete', T_('Delete')) . "</a>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get broadcast link.
|
||||
* @return string
|
||||
*/
|
||||
public static function get_broadcast_link()
|
||||
{
|
||||
$link = "<div class=\"broadcast-action\">";
|
||||
|
@ -171,6 +371,11 @@ class Broadcast extends database_object
|
|||
return $link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get unbroadcast link.
|
||||
* @param int $id
|
||||
* @return string
|
||||
*/
|
||||
public static function get_unbroadcast_link($id)
|
||||
{
|
||||
$link = "<div class=\"broadcast-action\">";
|
||||
|
@ -180,6 +385,11 @@ class Broadcast extends database_object
|
|||
return $link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get broadcasts from an user.
|
||||
* @param int $user_id
|
||||
* @return int[]
|
||||
*/
|
||||
public static function get_broadcasts($user_id)
|
||||
{
|
||||
$sql = "SELECT `id` FROM `broadcast` WHERE `user` = ?";
|
||||
|
@ -192,11 +402,22 @@ class Broadcast extends database_object
|
|||
return $broadcasts;
|
||||
}
|
||||
|
||||
public static function gc()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Get play url.
|
||||
*
|
||||
* @param int $oid
|
||||
* @param string $additional_params
|
||||
* @param string $player
|
||||
* @param boolean $local
|
||||
* @return string
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public static function play_url($oid, $additional_params='')
|
||||
public static function play_url($oid, $additional_params='', $player=null, $local=false)
|
||||
{
|
||||
return $oid;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -36,9 +36,21 @@ class Broadcast_Server implements MessageComponentInterface
|
|||
const BROADCAST_AUTH_SID = "AUTH_SID";
|
||||
|
||||
public $verbose;
|
||||
/**
|
||||
* @var ConnectionInterface[] $clients
|
||||
*/
|
||||
protected $clients;
|
||||
/**
|
||||
* @var string[] $sids
|
||||
*/
|
||||
protected $sids;
|
||||
/**
|
||||
* @var ConnectionInterface[] $listeners
|
||||
*/
|
||||
protected $listeners;
|
||||
/**
|
||||
* @var Broadcast[] $broadcasters
|
||||
*/
|
||||
protected $broadcasters;
|
||||
|
||||
public function __construct()
|
||||
|
@ -50,11 +62,20 @@ class Broadcast_Server implements MessageComponentInterface
|
|||
$this->broadcasters = array();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param \Ratchet\ConnectionInterface $conn
|
||||
*/
|
||||
public function onOpen(ConnectionInterface $conn)
|
||||
{
|
||||
$this->clients[$conn->resourceId] = $conn;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param \Ratchet\ConnectionInterface $from
|
||||
* @param string $msg
|
||||
*/
|
||||
public function onMessage(ConnectionInterface $from, $msg)
|
||||
{
|
||||
$commands = explode(';', $msg);
|
||||
|
@ -101,6 +122,11 @@ class Broadcast_Server implements MessageComponentInterface
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param int $song_id
|
||||
* @return string
|
||||
*/
|
||||
protected function getSongJS($song_id)
|
||||
{
|
||||
$media = array();
|
||||
|
@ -113,13 +139,18 @@ class Broadcast_Server implements MessageComponentInterface
|
|||
return WebPlayer::get_media_js_param($item[0]);
|
||||
}
|
||||
|
||||
protected function notifySong($from, $song_id)
|
||||
/**
|
||||
*
|
||||
* @param \Ratchet\ConnectionInterface $from
|
||||
* @param int $song_id
|
||||
*/
|
||||
protected function notifySong(ConnectionInterface $from, $song_id)
|
||||
{
|
||||
if ($this->isBroadcaster($from)) {
|
||||
$broadcast = $this->broadcasters[$from->resourceId];
|
||||
$clients = $this->getListeners($broadcast);
|
||||
|
||||
Session::extend(Stream::$session, 'stream');
|
||||
Session::extend(Stream::get_session(), 'stream');
|
||||
|
||||
$broadcast->update_song($song_id);
|
||||
$this->broadcastMessage($clients, self::BROADCAST_SONG, base64_encode($this->getSongJS($song_id)));
|
||||
|
@ -132,7 +163,12 @@ class Broadcast_Server implements MessageComponentInterface
|
|||
}
|
||||
}
|
||||
|
||||
protected function notifySongPosition($from, $song_position)
|
||||
/**
|
||||
*
|
||||
* @param \Ratchet\ConnectionInterface $from
|
||||
* @param int $song_position
|
||||
*/
|
||||
protected function notifySongPosition(ConnectionInterface $from, $song_position)
|
||||
{
|
||||
if ($this->isBroadcaster($from)) {
|
||||
$broadcast = $this->broadcasters[$from->resourceId];
|
||||
|
@ -151,12 +187,17 @@ class Broadcast_Server implements MessageComponentInterface
|
|||
}
|
||||
}
|
||||
|
||||
protected function notifyPlayerPlay($from, $play)
|
||||
/**
|
||||
*
|
||||
* @param \Ratchet\ConnectionInterface $from
|
||||
* @param boolean $play
|
||||
*/
|
||||
protected function notifyPlayerPlay(ConnectionInterface $from, $play)
|
||||
{
|
||||
if ($this->isBroadcaster($from)) {
|
||||
$broadcast = $this->broadcasters[$from->resourceId];
|
||||
$clients = $this->getListeners($broadcast);
|
||||
$this->broadcastMessage($clients, self::BROADCAST_PLAYER_PLAY, $play);
|
||||
$this->broadcastMessage($clients, self::BROADCAST_PLAYER_PLAY, $play ? 'true' : 'false');
|
||||
|
||||
if ($this->verbose) {
|
||||
echo "[" . time() ."][info]Broadcast " . $broadcast->id . " player state: " . $play . "." . "\r\n";
|
||||
|
@ -166,7 +207,31 @@ class Broadcast_Server implements MessageComponentInterface
|
|||
}
|
||||
}
|
||||
|
||||
protected function registerBroadcast($from, $broadcast_key)
|
||||
/**
|
||||
*
|
||||
* @param \Ratchet\ConnectionInterface $from
|
||||
*/
|
||||
protected function notifyEnded(ConnectionInterface $from)
|
||||
{
|
||||
if ($this->isBroadcaster($from)) {
|
||||
$broadcast = $this->broadcasters[$from->resourceId];
|
||||
$clients = $this->getListeners($broadcast);
|
||||
$this->broadcastMessage($clients, self::BROADCAST_ENDED);
|
||||
|
||||
if ($this->verbose) {
|
||||
echo "[" . time() ."][info]Broadcast " . $broadcast->id . " ended." . "\r\n";
|
||||
}
|
||||
} else {
|
||||
debug_event('broadcast', 'Action unauthorized.', '3');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param \Ratchet\ConnectionInterface $from
|
||||
* @param string $broadcast_key
|
||||
*/
|
||||
protected function registerBroadcast(ConnectionInterface $from, $broadcast_key)
|
||||
{
|
||||
$broadcast = Broadcast::get_broadcast($broadcast_key);
|
||||
if ($broadcast) {
|
||||
|
@ -179,7 +244,11 @@ class Broadcast_Server implements MessageComponentInterface
|
|||
}
|
||||
}
|
||||
|
||||
protected function unregisterBroadcast($conn)
|
||||
/**
|
||||
*
|
||||
* @param \Ratchet\ConnectionInterface $conn
|
||||
*/
|
||||
protected function unregisterBroadcast(ConnectionInterface $conn)
|
||||
{
|
||||
$broadcast = $this->broadcasters[$conn->resourceId];
|
||||
$clients = $this->getListeners($broadcast);
|
||||
|
@ -194,6 +263,11 @@ class Broadcast_Server implements MessageComponentInterface
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param int $broadcast_id
|
||||
* @return Broadcast
|
||||
*/
|
||||
protected function getRunningBroadcast($broadcast_id)
|
||||
{
|
||||
$broadcast = null;
|
||||
|
@ -206,7 +280,12 @@ class Broadcast_Server implements MessageComponentInterface
|
|||
return $broadcast;
|
||||
}
|
||||
|
||||
protected function registerListener($from, $broadcast_id)
|
||||
/**
|
||||
*
|
||||
* @param \Ratchet\ConnectionInterface $from
|
||||
* @param int $broadcast_id
|
||||
*/
|
||||
protected function registerListener(ConnectionInterface $from, $broadcast_id)
|
||||
{
|
||||
$broadcast = $this->getRunningBroadcast($broadcast_id);
|
||||
|
||||
|
@ -226,7 +305,12 @@ class Broadcast_Server implements MessageComponentInterface
|
|||
}
|
||||
}
|
||||
|
||||
protected function authSid($conn, $sid)
|
||||
/**
|
||||
*
|
||||
* @param \Ratchet\ConnectionInterface $conn
|
||||
* @param string $sid
|
||||
*/
|
||||
protected function authSid(ConnectionInterface $conn, $sid)
|
||||
{
|
||||
if (Session::exists('stream', $sid)) {
|
||||
$this->sids[$conn->resourceId] = $sid;
|
||||
|
@ -237,7 +321,11 @@ class Broadcast_Server implements MessageComponentInterface
|
|||
}
|
||||
}
|
||||
|
||||
protected function unregisterListener($conn)
|
||||
/**
|
||||
*
|
||||
* @param \Ratchet\ConnectionInterface $conn
|
||||
*/
|
||||
protected function unregisterListener(ConnectionInterface $conn)
|
||||
{
|
||||
foreach ($this->listeners as $broadcast_id => $brlisteners) {
|
||||
$lindex = array_search($conn, $brlisteners);
|
||||
|
@ -257,7 +345,11 @@ class Broadcast_Server implements MessageComponentInterface
|
|||
}
|
||||
}
|
||||
|
||||
protected function notifyNbListeners($broadcast)
|
||||
/**
|
||||
*
|
||||
* @param Broadcast $broadcast
|
||||
*/
|
||||
protected function notifyNbListeners(Broadcast $broadcast)
|
||||
{
|
||||
$broadcaster_id = array_search($broadcast, $this->broadcasters);
|
||||
if ($broadcaster_id) {
|
||||
|
@ -269,16 +361,32 @@ class Broadcast_Server implements MessageComponentInterface
|
|||
}
|
||||
}
|
||||
|
||||
protected function getListeners($broadcast)
|
||||
/**
|
||||
*
|
||||
* @param Broadcast $broadcast
|
||||
* @return \Ratchet\ConnectionInterface
|
||||
*/
|
||||
protected function getListeners(Broadcast $broadcast)
|
||||
{
|
||||
return $this->listeners[$broadcast->id];
|
||||
}
|
||||
|
||||
protected function isBroadcaster($conn)
|
||||
/**
|
||||
*
|
||||
* @param \Ratchet\ConnectionInterface $conn
|
||||
* @return boolean
|
||||
*/
|
||||
protected function isBroadcaster(ConnectionInterface $conn)
|
||||
{
|
||||
return array_key_exists($conn->resourceId, $this->broadcasters);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param \Ratchet\ConnectionInterface[] $clients
|
||||
* @param string $cmd
|
||||
* @param string $value
|
||||
*/
|
||||
protected function broadcastMessage($clients, $cmd, $value='')
|
||||
{
|
||||
$msg = $cmd . ':' . $value . ';';
|
||||
|
@ -291,6 +399,10 @@ class Broadcast_Server implements MessageComponentInterface
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param \Ratchet\ConnectionInterface $conn
|
||||
*/
|
||||
public function onClose(ConnectionInterface $conn)
|
||||
{
|
||||
if ($this->isBroadcaster($conn)) {
|
||||
|
@ -303,11 +415,20 @@ class Broadcast_Server implements MessageComponentInterface
|
|||
unset($this->sids[$conn->resourceId]);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param \Ratchet\ConnectionInterface $conn
|
||||
* @param \Exception $e
|
||||
*/
|
||||
public function onError(ConnectionInterface $conn, \Exception $e)
|
||||
{
|
||||
$conn->close();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_address()
|
||||
{
|
||||
$websocket_address = AmpConfig::get('websocket_address');
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -31,8 +31,17 @@
|
|||
*/
|
||||
class Browse extends Query
|
||||
{
|
||||
/**
|
||||
* @var boolean $show_header
|
||||
*/
|
||||
public $show_header;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param int|null $id
|
||||
* @param boolean $cached
|
||||
*/
|
||||
public function __construct($id = null, $cached = true)
|
||||
{
|
||||
parent::__construct($id, $cached);
|
||||
|
@ -48,6 +57,8 @@ class Browse extends Query
|
|||
* set_simple_browse
|
||||
* This sets the current browse object to a 'simple' browse method
|
||||
* which means use the base query provided and expand from there
|
||||
*
|
||||
* @param boolean $value
|
||||
*/
|
||||
public function set_simple_browse($value)
|
||||
{
|
||||
|
@ -58,6 +69,9 @@ class Browse extends Query
|
|||
/**
|
||||
* add_supplemental_object
|
||||
* Legacy function, need to find a better way to do that
|
||||
*
|
||||
* @param string $class
|
||||
* @param int $uid
|
||||
*/
|
||||
public function add_supplemental_object($class, $uid)
|
||||
{
|
||||
|
@ -71,6 +85,8 @@ class Browse extends Query
|
|||
* get_supplemental_objects
|
||||
* This returns an array of 'class','id' for additional objects that
|
||||
* need to be created before we start this whole browsing thing.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_supplemental_objects()
|
||||
{
|
||||
|
@ -84,11 +100,42 @@ class Browse extends Query
|
|||
|
||||
} // get_supplemental_objects
|
||||
|
||||
/**
|
||||
* update_browse_from_session
|
||||
* Restore the previous start index from something saved into the current session.
|
||||
*/
|
||||
public function update_browse_from_session()
|
||||
{
|
||||
if ($this->is_simple() && $this->get_start() == 0) {
|
||||
$name = 'browse_current_' . $this->get_type();
|
||||
if (isset($_SESSION[$name]) && isset($_SESSION[$name]['start']) && $_SESSION[$name]['start'] > 0) {
|
||||
|
||||
// Checking if value is suitable
|
||||
$start = $_SESSION[$name]['start'];
|
||||
if ($this->get_offset() > 0) {
|
||||
|
||||
$set_page = floor($start / $this->get_offset());
|
||||
if ($this->get_total() > $this->get_offset()) {
|
||||
$total_pages = ceil($this->get_total() / $this->get_offset());
|
||||
} else {
|
||||
$total_pages = 0;
|
||||
}
|
||||
|
||||
if ($set_page >= 0 && $set_page <= $total_pages) {
|
||||
$this->set_start($start);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* show_objects
|
||||
* This takes an array of objects
|
||||
* and requires the correct template based on the
|
||||
* type that we are currently browsing
|
||||
*
|
||||
* @param int[] $object_ids
|
||||
*/
|
||||
public function show_objects($object_ids = null, $argument = null)
|
||||
{
|
||||
|
@ -100,9 +147,8 @@ class Browse extends Query
|
|||
|
||||
// Limit is based on the user's preferences if this is not a
|
||||
// simple browse because we've got too much here
|
||||
if ((count($object_ids) > $this->get_start()) &&
|
||||
! $this->is_simple() &&
|
||||
! $this->is_static_content()) {
|
||||
if ($this->get_start() >= 0 && (count($object_ids) > $this->get_start()) &&
|
||||
! $this->is_simple()) {
|
||||
$object_ids = array_slice(
|
||||
$object_ids,
|
||||
$this->get_start(),
|
||||
|
@ -133,37 +179,53 @@ class Browse extends Query
|
|||
$match = ' (' . $filter_value . ')';*/
|
||||
} elseif ($filter_value = $this->get_filter('catalog')) {
|
||||
// Get the catalog title
|
||||
$catalog = Catalog::create_from_id($filter_value);
|
||||
$catalog = Catalog::create_from_id(intval($filter_value));
|
||||
$match = ' (' . $catalog->name . ')';
|
||||
}
|
||||
|
||||
$type = $this->get_type();
|
||||
|
||||
// Update the session value only if it's allowed on the current browser
|
||||
if ($this->get_update_session()) {
|
||||
$_SESSION['browse_current_' . $type]['start'] = $browse->get_start();
|
||||
}
|
||||
|
||||
// Set the correct classes based on type
|
||||
$class = "box browse_" . $type;
|
||||
|
||||
debug_event('browse', 'Called for type {'.$type.'}', '5');
|
||||
$argument_param = ($argument ? '&argument=' . scrub_in($argument) : '');
|
||||
|
||||
debug_event('browse', 'Show objects called for type {'.$type.'}', '5');
|
||||
|
||||
$limit_threshold = $this->get_threshold();
|
||||
|
||||
// Switch on the type of browsing we're doing
|
||||
switch ($type) {
|
||||
case 'song':
|
||||
$box_title = T_('Songs') . $match;
|
||||
Song::build_cache($object_ids);
|
||||
Song::build_cache($object_ids, $limit_threshold);
|
||||
$box_req = AmpConfig::get('prefix') . '/templates/show_songs.inc.php';
|
||||
break;
|
||||
case 'album':
|
||||
$box_title = T_('Albums') . $match;
|
||||
Album::build_cache($object_ids);
|
||||
$allow_group_disks = $argument;
|
||||
$box_title = T_('Albums') . $match;
|
||||
if (is_array($argument)) {
|
||||
$allow_group_disks = $argument['group_disks'];
|
||||
if ($argument['title']) {
|
||||
$box_title = $argument['title'];
|
||||
}
|
||||
} else {
|
||||
$allow_group_disks = false;
|
||||
}
|
||||
$box_req = AmpConfig::get('prefix') . '/templates/show_albums.inc.php';
|
||||
break;
|
||||
case 'user':
|
||||
$box_title = T_('Manage Users') . $match;
|
||||
$box_title = T_('Users') . $match;
|
||||
$box_req = AmpConfig::get('prefix') . '/templates/show_users.inc.php';
|
||||
break;
|
||||
case 'artist':
|
||||
$box_title = T_('Artists') . $match;
|
||||
Artist::build_cache($object_ids, 'extra');
|
||||
Artist::build_cache($object_ids, true, $limit_threshold);
|
||||
$box_req = AmpConfig::get('prefix') . '/templates/show_artists.inc.php';
|
||||
break;
|
||||
case 'live_stream':
|
||||
|
@ -187,7 +249,7 @@ class Browse extends Query
|
|||
break;
|
||||
case 'smartplaylist':
|
||||
$box_title = T_('Smart Playlists') . $match;
|
||||
$box_req = AmpConfig::get('prefix') . '/templates/show_smartplaylists.inc.php';
|
||||
$box_req = AmpConfig::get('prefix') . '/templates/show_searches.inc.php';
|
||||
break;
|
||||
case 'catalog':
|
||||
$box_title = T_('Catalogs');
|
||||
|
@ -204,6 +266,7 @@ class Browse extends Query
|
|||
break;
|
||||
case 'video':
|
||||
Video::build_cache($object_ids);
|
||||
$video_type = 'video';
|
||||
$box_title = T_('Videos');
|
||||
$box_req = AmpConfig::get('prefix') . '/templates/show_videos.inc.php';
|
||||
break;
|
||||
|
@ -231,12 +294,52 @@ class Browse extends Query
|
|||
$box_title = T_('Broadcasts');
|
||||
$box_req = AmpConfig::get('prefix') . '/templates/show_broadcasts.inc.php';
|
||||
break;
|
||||
case 'license':
|
||||
$box_title = T_('Media Licenses');
|
||||
$box_req = AmpConfig::get('prefix') . '/templates/show_manage_license.inc.php';
|
||||
break;
|
||||
case 'tvshow':
|
||||
$box_title = T_('TV Shows');
|
||||
$box_req = AmpConfig::get('prefix') . '/templates/show_tvshows.inc.php';
|
||||
break;
|
||||
case 'tvshow_season':
|
||||
$box_title = T_('Seasons');
|
||||
$box_req = AmpConfig::get('prefix') . '/templates/show_tvshow_seasons.inc.php';
|
||||
break;
|
||||
case 'tvshow_episode':
|
||||
$box_title = T_('Episodes');
|
||||
$video_type = $type;
|
||||
$box_req = AmpConfig::get('prefix') . '/templates/show_videos.inc.php';
|
||||
break;
|
||||
case 'movie':
|
||||
$box_title = T_('Movies');
|
||||
$video_type = $type;
|
||||
$box_req = AmpConfig::get('prefix') . '/templates/show_videos.inc.php';
|
||||
break;
|
||||
case 'clip':
|
||||
$box_title = T_('Clips');
|
||||
$video_type = $type;
|
||||
$box_req = AmpConfig::get('prefix') . '/templates/show_videos.inc.php';
|
||||
break;
|
||||
case 'personal_video':
|
||||
$box_title = T_('Personal Videos');
|
||||
$video_type = $type;
|
||||
$box_req = AmpConfig::get('prefix') . '/templates/show_videos.inc.php';
|
||||
break;
|
||||
case 'label':
|
||||
$box_title = T_('Labels');
|
||||
$box_req = AmpConfig::get('prefix') . '/templates/show_labels.inc.php';
|
||||
break;
|
||||
case 'pvmsg':
|
||||
$box_title = T_('Private Messages');
|
||||
$box_req = AmpConfig::get('prefix') . '/templates/show_pvmsgs.inc.php';
|
||||
break;
|
||||
default:
|
||||
// Rien a faire
|
||||
break;
|
||||
} // end switch on type
|
||||
|
||||
Ajax::start_container('browse_content_' . $type, 'browse_content');
|
||||
Ajax::start_container($this->get_content_div(), 'browse_content');
|
||||
if ($this->get_show_header()) {
|
||||
if (isset($box_req) && isset($box_title)) {
|
||||
UI::show_box_top($box_title, $class);
|
||||
|
@ -252,31 +355,32 @@ class Browse extends Query
|
|||
UI::show_box_bottom();
|
||||
}
|
||||
echo '<script type="text/javascript">';
|
||||
echo Ajax::action('?page=browse&action=get_filters&browse_id=' . $this->id, '');
|
||||
echo Ajax::action('?page=browse&action=get_filters&browse_id=' . $this->id . $argument_param, '');
|
||||
echo ';</script>';
|
||||
} else {
|
||||
if (!$this->get_use_pages()) {
|
||||
$this->show_next_link();
|
||||
$this->show_next_link($argument);
|
||||
}
|
||||
}
|
||||
Ajax::end_container();
|
||||
|
||||
} // show_object
|
||||
|
||||
public function show_next_link()
|
||||
public function show_next_link($argument = null)
|
||||
{
|
||||
$limit = $this->get_offset();
|
||||
$start = $this->get_start();
|
||||
$total = $this->get_total();
|
||||
$limit = $this->get_offset();
|
||||
$start = $this->get_start();
|
||||
$total = $this->get_total();
|
||||
$next_offset = $start + $limit;
|
||||
if ($next_offset <= $total) {
|
||||
echo '<a class="jscroll-next" href="' . AmpConfig::get('ajax_url') . '?page=browse&action=page&browse_id=' . $this->id . '&start=' . $next_offset . '&xoutput=raw&xoutputnode=browse_content_' . $this->get_type() . '&show_header=false">' . T_('More') . '</a>';
|
||||
echo '<a class="jscroll-next" href="' . AmpConfig::get('ajax_url') . '?page=browse&action=page&browse_id=' . $this->id . '&start=' . $next_offset . '&xoutput=raw&xoutputnode='. $this->get_content_div() . '&show_header=false' . $argument . '">' . T_('More') . '</a>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set_filter_from_request
|
||||
* //FIXME
|
||||
* @param array $request
|
||||
*/
|
||||
public function set_filter_from_request($request)
|
||||
{
|
||||
|
@ -300,6 +404,11 @@ class Browse extends Query
|
|||
}
|
||||
} // set_filter_from_request
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $custom_base
|
||||
*/
|
||||
public function set_type($type, $custom_base = '')
|
||||
{
|
||||
$cn = 'browse_' . $type . '_pages';
|
||||
|
@ -321,6 +430,11 @@ class Browse extends Query
|
|||
parent::set_type($type, $custom_base);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $option
|
||||
* @param string $value
|
||||
*/
|
||||
public function save_cookie_params($option, $value)
|
||||
{
|
||||
if ($this->get_type()) {
|
||||
|
@ -328,36 +442,96 @@ class Browse extends Query
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param boolean $use_pages
|
||||
*/
|
||||
public function set_use_pages($use_pages)
|
||||
{
|
||||
$this->save_cookie_params('pages', $use_pages ? 'true' : 'false');
|
||||
$this->_state['use_pages'] = $use_pages;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function get_use_pages()
|
||||
{
|
||||
return $this->_state['use_pages'];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param boolean $use_alpha
|
||||
*/
|
||||
public function set_use_alpha($use_alpha)
|
||||
{
|
||||
$this->save_cookie_params('alpha', $use_alpha ? 'true' : 'false');
|
||||
$this->_state['use_alpha'] = $use_alpha;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function get_use_alpha()
|
||||
{
|
||||
return $this->_state['use_alpha'];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param boolean $show_header
|
||||
*/
|
||||
public function set_show_header($show_header)
|
||||
{
|
||||
$this->show_header = $show_header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow the current page to be save into the current session
|
||||
* @param boolean $update_session
|
||||
*/
|
||||
public function set_update_session($update_session)
|
||||
{
|
||||
$this->_state['update_session'] = $update_session;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function get_show_header()
|
||||
{
|
||||
return $this->show_header;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function get_update_session()
|
||||
{
|
||||
return $this->_state['update_session'];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $threshold
|
||||
*/
|
||||
public function set_threshold($threshold)
|
||||
{
|
||||
$this->_state['threshold'] = $threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_threshold()
|
||||
{
|
||||
return $this->_state['threshold'];
|
||||
}
|
||||
|
||||
} // browse
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2014 Ampache.org
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
|
@ -20,7 +20,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
class Channel extends database_object
|
||||
class Channel extends database_object implements media, library_item
|
||||
{
|
||||
public $id;
|
||||
public $is_private;
|
||||
|
@ -37,6 +37,11 @@ class Channel extends database_object
|
|||
public $loop;
|
||||
public $bitrate;
|
||||
public $name;
|
||||
public $description;
|
||||
|
||||
public $header_chunk;
|
||||
public $chunk_size = 4096;
|
||||
private $header_chunk_remainder = 0;
|
||||
|
||||
public $tags;
|
||||
public $f_tags;
|
||||
|
@ -100,10 +105,12 @@ class Channel extends database_object
|
|||
{
|
||||
$tags = Tag::get_object_tags('channel', $this->id);
|
||||
$genre = "";
|
||||
foreach ($tags as $tag) {
|
||||
$genre .= $tag['name'] . ' ';
|
||||
if ($tags) {
|
||||
foreach ($tags as $tag) {
|
||||
$genre .= $tag['name'] . ' ';
|
||||
}
|
||||
$genre = trim($genre);
|
||||
}
|
||||
$genre = trim($genre);
|
||||
|
||||
return $genre;
|
||||
}
|
||||
|
@ -140,16 +147,18 @@ class Channel extends database_object
|
|||
return false;
|
||||
}
|
||||
|
||||
public function update($data)
|
||||
public function update(array $data)
|
||||
{
|
||||
if (isset($data['edit_tags'])) {
|
||||
Tag::update_tag_list($data['edit_tags'], 'channel', $this->id);
|
||||
Tag::update_tag_list($data['edit_tags'], 'channel', $this->id, true);
|
||||
}
|
||||
|
||||
$sql = "UPDATE `channel` SET `name` = ?, `description` = ?, `url` = ?, `interface` = ?, `port` = ?, `fixed_endpoint` = ?, `admin_password` = ?, `is_private` = ?, `max_listeners` = ?, `random` = ?, `loop` = ?, `stream_type` = ?, `bitrate` = ?, `object_id` = ? " .
|
||||
"WHERE `id` = ?";
|
||||
$params = array($data['name'], $data['description'], $data['url'], $data['interface'], $data['port'], (!empty($data['interface']) && !empty($data['port'])), $data['admin_password'], !empty($data['private']), $data['max_listeners'], $data['random'], $data['loop'], $data['stream_type'], $data['bitrate'], $data['object_id'], $this->id);
|
||||
return Dba::write($sql, $params);
|
||||
Dba::write($sql, $params);
|
||||
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public static function format_type($type)
|
||||
|
@ -157,10 +166,10 @@ class Channel extends database_object
|
|||
switch ($type) {
|
||||
case 'playlist':
|
||||
$ftype = $type;
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
$ftype = '';
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ftype;
|
||||
|
@ -178,10 +187,71 @@ class Channel extends database_object
|
|||
}
|
||||
}
|
||||
|
||||
public function format()
|
||||
public function format($details = true)
|
||||
{
|
||||
$this->tags = Tag::get_top_tags('channel', $this->id);
|
||||
$this->f_tags = Tag::get_display($this->tags);
|
||||
if ($details) {
|
||||
$this->tags = Tag::get_top_tags('channel', $this->id);
|
||||
$this->f_tags = Tag::get_display($this->tags, true, 'channel');
|
||||
}
|
||||
}
|
||||
|
||||
public function get_keywords()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function get_fullname()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function get_parent()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function get_childrens()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function search_childrens($name)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function get_medias($filter_type = null)
|
||||
{
|
||||
$medias = array();
|
||||
if (!$filter_type || $filter_type == 'channel') {
|
||||
$medias[] = array(
|
||||
'object_type' => 'channel',
|
||||
'object_id' => $this->id
|
||||
);
|
||||
}
|
||||
return $medias;
|
||||
}
|
||||
|
||||
public function get_user_owner()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function get_default_art_kind()
|
||||
{
|
||||
return 'default';
|
||||
}
|
||||
|
||||
public function get_description()
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function display_art($thumb = 2)
|
||||
{
|
||||
if (Art::has_db($this->id, 'channel')) {
|
||||
Art::display('channel', $this->id, $this->get_fullname(), $thumb, $this->link);
|
||||
}
|
||||
}
|
||||
|
||||
public function get_target_object()
|
||||
|
@ -345,24 +415,64 @@ class Channel extends database_object
|
|||
if ($this->media != null) {
|
||||
// Stream not yet initialized for this media, start it
|
||||
if (!$this->transcoder) {
|
||||
$this->transcoder = Stream::start_transcode($this->media, $this->stream_type, $this->bitrate);
|
||||
$options = array(
|
||||
'bitrate' => $this->bitrate
|
||||
);
|
||||
$this->transcoder = Stream::start_transcode($this->media, $this->stream_type, null, $options);
|
||||
$this->media_bytes_streamed = 0;
|
||||
}
|
||||
|
||||
if (is_resource($this->transcoder['handle'])) {
|
||||
|
||||
$chunk = fread($this->transcoder['handle'], 4096);
|
||||
if (ftell($this->transcoder['handle']) == 0)
|
||||
$this->header_chunk = '';
|
||||
$chunk = fread($this->transcoder['handle'], $this->chunk_size);
|
||||
$this->media_bytes_streamed += strlen($chunk);
|
||||
|
||||
if ((ftell($this->transcoder['handle']) < 10000 && strtolower($this->stream_type) == "ogg") || $this->header_chunk_remainder) {
|
||||
//debug_event('channel', 'File handle pointer: ' . ftell($this->transcoder['handle']) ,'5');
|
||||
$clchunk = $chunk;
|
||||
|
||||
if ($this->header_chunk_remainder) {
|
||||
$this->header_chunk .= substr($clchunk, 0, $this->header_chunk_remainder);
|
||||
if (strlen($clchunk) >= $this->header_chunk_remainder) {
|
||||
$clchunk = substr($clchunk, $this->header_chunk_remainder);
|
||||
$this->header_chunk_remainder = 0;
|
||||
} else {
|
||||
$this->header_chunk_remainder = $this->header_chunk_remainder - strlen($clchunk);
|
||||
$clchunk = '';
|
||||
}
|
||||
}
|
||||
// see bin/channel_run.inc for explanation what's happening here
|
||||
while ($this->strtohex(substr($clchunk, 0, 4)) == "4F676753") {
|
||||
$hex = $this->strtohex(substr($clchunk, 0, 27));
|
||||
$ogg_nr_of_segments = hexdec(substr($hex, 26*2, 2));
|
||||
if ((substr($clchunk, 27 + $ogg_nr_of_segments + 1, 6) == "vorbis") || (substr($clchunk, 27 + $ogg_nr_of_segments, 4) == "Opus")) {
|
||||
$hex .= $this->strtohex(substr($clchunk, 27, $ogg_nr_of_segments));
|
||||
$ogg_sum_segm_laces = 0;
|
||||
for ($segm = 0; $segm < $ogg_nr_of_segments; $segm++) {
|
||||
$ogg_sum_segm_laces += hexdec(substr($hex, 27*2 + $segm*2, 2));
|
||||
}
|
||||
$this->header_chunk .= substr($clchunk, 0, 27 + $ogg_nr_of_segments + $ogg_sum_segm_laces);
|
||||
if (strlen($clchunk) < (27 + $ogg_nr_of_segments + $ogg_sum_segm_laces))
|
||||
$this->header_chunk_remainder = (int) (27 + $ogg_nr_of_segments + $ogg_sum_segm_laces - strlen($clchunk));
|
||||
$clchunk = substr($clchunk, 27 + $ogg_nr_of_segments + $ogg_sum_segm_laces);
|
||||
} else //no more interesting headers
|
||||
$clchunk = '';
|
||||
}
|
||||
}
|
||||
//debug_event('channel', 'File handle pointer: ' . ftell($this->transcoder['handle']) ,'5');
|
||||
//debug_event('channel', 'CHUNK : ' . $chunk, '5');
|
||||
//debug_event('channel', 'Chunk size: ' . strlen($chunk) ,'5');
|
||||
|
||||
// End of file, prepare to move on for next call
|
||||
if (feof($this->transcoder['handle'])) {
|
||||
$this->media->set_played();
|
||||
$this->media->set_played(-1, 'Ampache', array());
|
||||
if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
|
||||
fread($this->transcoder['stderr'], 4096);
|
||||
fclose($this->transcoder['stderr']);
|
||||
}
|
||||
fclose($this->transcoder['handle']);
|
||||
proc_close($this->transcoder['process']);
|
||||
Stream::kill_process($this->transcoder);
|
||||
|
||||
$this->media = null;
|
||||
$this->transcoder = null;
|
||||
|
@ -381,10 +491,55 @@ class Channel extends database_object
|
|||
return $chunk;
|
||||
}
|
||||
|
||||
public static function play_url($oid, $additional_params='')
|
||||
/**
|
||||
* get_catalogs
|
||||
*
|
||||
* Get all catalog ids related to this item.
|
||||
* @return int[]
|
||||
*/
|
||||
public function get_catalogs()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public static function play_url($oid, $additional_params='', $player=null, $local=false)
|
||||
{
|
||||
$channel = new Channel($oid);
|
||||
return $channel->get_stream_proxy_url() . '?rt=' . time() . '&filename=' . urlencode($channel->name) . '.' . $channel->stream_type . $additional_params;
|
||||
}
|
||||
|
||||
public function get_stream_types($player = null)
|
||||
{
|
||||
// Transcode is mandatory to keep a consistant stream
|
||||
return array('transcode');
|
||||
}
|
||||
|
||||
public function get_stream_name()
|
||||
{
|
||||
return $this->get_fullname();
|
||||
}
|
||||
|
||||
public function set_played($user, $agent, $location)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public function get_transcode_settings($target = null, $player = null, $options=array())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function gc()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private function strtohex($x)
|
||||
{
|
||||
$s='';
|
||||
foreach(str_split($x) as $c) $s.=sprintf("%02X",ord($c));
|
||||
return($s);
|
||||
}
|
||||
|
||||
|
||||
} // end of channel class
|
||||
|
|
141
sources/lib/class/clip.class.php
Normal file
|
@ -0,0 +1,141 @@
|
|||
<?php
|
||||
/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
|
||||
/**
|
||||
*
|
||||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||||
* Copyright 2001 - 2015 Ampache.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License v2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
class Clip extends Video
|
||||
{
|
||||
public $artist;
|
||||
public $song;
|
||||
public $video;
|
||||
|
||||
public $f_artist;
|
||||
public $f_song;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* This pulls the clip information from the database and returns
|
||||
* a constructed object
|
||||
*/
|
||||
public function __construct($id)
|
||||
{
|
||||
parent::__construct($id);
|
||||
|
||||
$info = $this->get_info($id);
|
||||
foreach ($info as $key=>$value) {
|
||||
$this->$key = $value;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} // Constructor
|
||||
|
||||
/**
|
||||
* gc
|
||||
*
|
||||
* This cleans out unused clips
|
||||
*/
|
||||
public static function gc()
|
||||
{
|
||||
$sql = "DELETE FROM `clip` USING `clip` LEFT JOIN `video` ON `video`.`id` = `clip`.`id` " .
|
||||
"WHERE `video`.`id` IS NULL";
|
||||
Dba::write($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* create
|
||||
* This takes a key'd array of data as input and inserts a new clip entry, it returns the record id
|
||||
*/
|
||||
public static function insert(array $data, $gtypes = array(), $options = array())
|
||||
{
|
||||
$sql = "INSERT INTO `clip` (`id`,`artist`,`song`) " .
|
||||
"VALUES (?, ?, ?)";
|
||||
Dba::write($sql, array($data['id'], $data['artist'], $data['song']));
|
||||
|
||||
return $data['id'];
|
||||
|
||||
} // create
|
||||
|
||||
/**
|
||||
* update
|
||||
* This takes a key'd array of data as input and updates a clip entry
|
||||
*/
|
||||
public function update(array $data)
|
||||
{
|
||||
$sql = "UPDATE `clip` SET `artist` = ?, `song` = ? WHERE `id` = ?";
|
||||
Dba::write($sql, array($data['artist'], $data['song'], $this->id));
|
||||
|
||||
return $this->id;
|
||||
|
||||
} // update
|
||||
|
||||
/**
|
||||
* format
|
||||
* this function takes the object and reformats some values
|
||||
*/
|
||||
|
||||
public function format($details = true)
|
||||
{
|
||||
parent::format($details);
|
||||
|
||||
if ($details) {
|
||||
if ($this->artist) {
|
||||
$artist = new Artist($this->artist);
|
||||
$artist->format();
|
||||
$this->f_artist = $artist->link;
|
||||
}
|
||||
|
||||
if ($this->song) {
|
||||
$song = new Song($this->song);
|
||||
$song->format();
|
||||
$this->f_song = $song->f_link;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} //format
|
||||
|
||||
/**
|
||||
* Get item keywords for metadata searches.
|
||||
* @return array
|
||||
*/
|
||||
public function get_keywords()
|
||||
{
|
||||
$keywords = parent::get_keywords();
|
||||
if ($this->artist) {
|
||||
$keywords['artist'] = array('important' => true,
|
||||
'label' => T_('Artist'),
|
||||
'value' => $this->f_artist);
|
||||
}
|
||||
|
||||
return $keywords;
|
||||
}
|
||||
|
||||
public function get_parent()
|
||||
{
|
||||
if ($this->artist) {
|
||||
return array('object_type' => 'artist', 'object_id' => $this->artist);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
} // Clip class
|