+ struct private_plm_data *ppd = self->private_data;
+
+ shm_detach(ppd->client_data);
+ shm_destroy(ppd->client_data_shm_id);
+ mutex_destroy(ppd->server_mutex);
+ mutex_destroy(ppd->client_mutex);
+ free(ppd);
+ free_playlist_contents();
+ free(playlist);
+ playlist = NULL;
+ playlist_len = 0;
+ playlist_size = 0;
+}
+
+static void plm_post_select(__unused fd_set *rfds, __unused fd_set *wfds)
+{
+ struct private_plm_data *ppd = self->private_data;
+ struct plm_client_data *pcd = ppd->client_data;
+ int ret;
+ void *shm;
+
+ mutex_lock(ppd->server_mutex);
+ if (!pcd->size)
+ goto out;
+ free_playlist_contents();
+ ret = shm_attach(pcd->shm_id, ATTACH_RW, &shm);
+ if (ret < 0) {
+ PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret));
+ goto out;
+ }
+ PARA_DEBUG_LOG("loading new playlist (%d bytes)\n", pcd->size);
+ ret = for_each_line((char *)shm, pcd->size, &playlist_add);
+ shm_detach(shm);
+ PARA_NOTICE_LOG("new playlist (%d entries)\n", playlist_len);
+ pcd->retval = 1;
+ pcd->size = 0;
+ mutex_unlock(pcd->mutex);
+out:
+ mutex_unlock(ppd->server_mutex);
+}
+
+void plm_update_audio_file(char *audio_file)
+{
+ unsigned i;
+
+ for (i = 0; i < playlist_len; i++) {
+ unsigned j = (current_playlist_entry + i) % playlist_len;
+ if (strcmp(playlist[j], audio_file))
+ continue;
+ current_playlist_entry = (j + 1) % playlist_len;
+ }