138 * Rebuilds the copy of the playlist in RAM |
138 * Rebuilds the copy of the playlist in RAM |
139 */ |
139 */ |
140 |
140 |
141 $playlist_last_md5 = ''; |
141 $playlist_last_md5 = ''; |
142 |
142 |
143 function rebuild_playlist() |
143 function rebuild_playlist($force = false, $from_ipc = false) |
144 { |
144 { |
145 // import what we need |
145 // import what we need |
146 global $playlist, $amarok_home; |
146 global $playlist, $amarok_home; |
147 // sync and load the playlist file |
147 // sync and load the playlist file |
148 $playlist_file = dcop_action('playlist', 'saveCurrentPlaylist'); |
148 // if we're coming from IPC, don't call DCOP, just load the existing file |
|
149 // this prevents the file from being generated 20 times and thus sometimes |
|
150 // causing simplexml to read a half-written file |
|
151 if ( !$from_ipc ) |
|
152 { |
|
153 $playlist_file = dcop_action('playlist', 'saveCurrentPlaylist'); |
|
154 } |
|
155 else |
|
156 { |
|
157 $playlist_file = $from_ipc; |
|
158 } |
149 // do we have amarok's home? |
159 // do we have amarok's home? |
150 if ( !$amarok_home ) |
160 if ( !$amarok_home ) |
151 $amarok_home = dirname($playlist_file); |
161 $amarok_home = dirname($playlist_file); |
152 // check MD5 - if it's not changed, exit to save CPU cycles |
162 // check MD5 - if it's not changed, exit to save CPU cycles |
153 global $playlist_last_md5; |
163 global $playlist_last_md5; |
154 $effective_md5 = md5_playlist_file($playlist_file); |
164 $effective_md5 = md5_playlist_file($playlist_file); |
155 if ( $playlist_last_md5 == $effective_md5 ) |
165 if ( $playlist_last_md5 == $effective_md5 && !$force ) |
156 { |
166 { |
157 return true; |
167 return true; |
158 } |
168 } |
159 status('Rebuilding playlist cache'); |
169 status('Rebuilding playlist cache'); |
160 $playlist_last_md5 = $effective_md5; |
170 $playlist_last_md5 = $effective_md5; |
161 // start XML parser |
171 $originalplaylist = $playlist_file; |
162 try |
172 $xml = false; |
163 { |
173 $unlinkplaylist = false; |
164 $xml = simplexml_load_file($playlist_file); |
174 while ( !$xml ) |
165 } |
175 { |
166 catch ( Exception $e ) |
176 // start XML parser |
167 { |
177 try |
168 burnout("Caught exception trying to load playlist file:\n$e"); |
178 { |
169 } |
179 $xml = @simplexml_load_file($playlist_file); |
|
180 if ( $xml ) |
|
181 break; |
|
182 |
|
183 // if we can't load it, just wait - another process might have it loaded |
|
184 warning('Could not load playlist file; maybe another Greyhound thread has it loaded? Waiting half a second.'); |
|
185 usleep(500000); |
|
186 } |
|
187 catch ( Exception $e ) |
|
188 { |
|
189 burnout("Caught exception trying to load playlist file:\n$e"); |
|
190 } |
|
191 } |
|
192 |
170 $attribs = $xml->attributes(); |
193 $attribs = $xml->attributes(); |
171 if ( @$attribs['product'] != 'Amarok' ) |
194 if ( @$attribs['product'] != 'Amarok' ) |
172 { |
195 { |
173 burnout('Playlist is not in Amarok format'); |
196 burnout('Playlist is not in Amarok format'); |
174 } |
197 } |
184 'length' => seconds_to_str(intval($child->Length)), |
207 'length' => seconds_to_str(intval($child->Length)), |
185 'length_int' => intval($child->Length) |
208 'length_int' => intval($child->Length) |
186 ); |
209 ); |
187 $playlist[] = $item; |
210 $playlist[] = $item; |
188 } |
211 } |
189 // if we're a child process, signal the parent to update |
212 if ( $unlinkplaylist ) |
190 if ( defined('HTTPD_WS_CHILD') ) |
213 { |
191 { |
214 unlink($playlist_file); |
192 global $httpd; |
215 } |
193 posix_kill($httpd->parent_pid, SIGHUP); |
216 // tell all other worker threads to reload the playlist as well |
|
217 global $httpd; |
|
218 if ( is_object($httpd) && !$from_ipc ) |
|
219 { |
|
220 $httpd->threader->ipc_send(array( |
|
221 'action' => 'reloadplaylist', |
|
222 'propagate' => true, |
|
223 'playlist_file' => $playlist_file |
|
224 )); |
|
225 } |
|
226 } |
|
227 |
|
228 function rebuild_playlist_ipc($command, $threader) |
|
229 { |
|
230 status('IPC playlist rebuild received'); |
|
231 if ( isset($command['playlist']) ) |
|
232 { |
|
233 status('IPC playlist rebuild: using playlist sent in IPC packet; length: ' . strlen($command['playlist'])); |
|
234 $GLOBALS['playlist'] = $command['playlist']; |
|
235 } |
|
236 else |
|
237 { |
|
238 rebuild_playlist(true, $command['playlist_file']); |
194 } |
239 } |
195 } |
240 } |
196 |
241 |
197 /** |
242 /** |
198 * Builds the correct MD5 check for the specified playlist XML file. This is designed to base on the list of actual tracks, disregarding |
243 * Builds the correct MD5 check for the specified playlist XML file. This is designed to base on the list of actual tracks, disregarding |