Peter Siebel - Practical Common Lisp

Здесь есть возможность читать онлайн «Peter Siebel - Practical Common Lisp» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Год выпуска: 2005, ISBN: 2005, Издательство: Apress, Жанр: Программирование, на английском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

Practical Common Lisp: краткое содержание, описание и аннотация

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Practical Common Lisp»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

Practical Common Lisp — читать онлайн бесплатно полную книгу (весь текст) целиком

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Practical Common Lisp», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

By storing the list of songs as a table, you can use the database functions from Chapter 27 to manipulate the playlist: you can add to the playlist with insert-row, delete songs with delete-rows, and reorder the playlist with sort-rowsand shuffle-table.

The current-songand current-idxslots keep track of which song is playing: current-songis an actual songobject, while current-idxis the index into the songs-tableof the row representing the current song. You'll see in the section "Manipulating the Playlist" how to make sure current-songis updated whenever current-idxchanges.

The orderingand shuffleslots hold information about how the songs in songs-tableare to be ordered. The orderingslot holds a keyword that tells how the songs-tableshould be sorted when it's not shuffled. The legal values are :genre, :artist, :album, and :song. The shuffleslot holds one of the keywords :none, :song, or :album, which specifies how songs-tableshould be shuffled, if at all.

The repeatslot also holds a keyword, one of :none, :song, or :all, which specifies the repeat mode for the playlist. If repeatis :none, after the last song in the songs-tablehas been played, the current-songgoes back to a default MP3. When :repeatis :song, the playlist keeps returning the same current-songforever. And if it's :all, after the last song, current-songgoes back to the first song.

The user-agentslot holds the value of the User-Agent header sent by the MP3 client in its request for the stream. You need to hold onto this value purely for use in the Web interface—the User-Agent header identifies the program that made the request, so you can display the value on the page that lists all the playlists to make it easier to tell which playlist goes with which connection when multiple clients connect.

Finally, the lockslot holds a process lock created with the function make-process-lock, which is part of Allegro's MULTIPROCESSINGpackage. You'll need to use that lock in certain functions that manipulate playlistobjects to ensure that only one thread at a time manipulates a given playlist object. You can define the following macro, built upon the with-process-lockmacro from MULTIPROCESSING, to give an easy way to wrap a body of code that should be performed while holding a playlist's lock:

(defmacro with-playlist-locked ((playlist) &body body)

`(with-process-lock ((lock ,playlist))

,@body))

The with-process-lockmacro acquires exclusive access to the process lock given and then executes the body forms, releasing the lock afterward. By default, with-process-lockallows recursive locks, meaning the same thread can safely acquire the same lock multiple times.

Playlists As Song Sources

To use playlists as a source of songs for the Shoutcast server, you'll need to implement a method on the generic function find-song-sourcefrom Chapter 28. Since you're going to have multiple playlists, you need a way to find the right one for each client that connects to the server. The mapping part is easy—you can define a variable that holds an EQUAL hash table that you can use to map from some identifier to the playlistobject.

(defvar *playlists* (make-hash-table :test #'equal))

You'll also need to define a process lock to protect access to this hash table like this:

(defparameter *playlists-lock* (make-process-lock :name "playlists-lock"))

Then define a function that looks up a playlist given an ID, creating a new playlistobject if necessary and using with-process-lockto ensure that only one thread at a time manipulates the hash table. [306] The intricacies of concurrent programming are beyond the scope of this book. The basic idea is that if you have multiple threads of control—as you will in this application with some threads running the shoutcast function and other threads responding to requests from the browser—then you need to make sure only one thread at a time manipulates an object in order to prevent one thread from seeing the object in an inconsistent state while another thread is working on it. In this function, for instance, if two new MP3 clients are connecting at the same time, they'd both try to add an entry to *playlists* and might interfere with each other. The with-process-lock ensures that each thread gets exclusive access to the hash table for long enough to do the work it needs to do.

(defun lookup-playlist (id)

(with-process-lock (*playlists-lock*)

(or (gethash id *playlists*)

(setf (gethash id *playlists*) (make-instance 'playlist :id id)))))

Then you can implement find-song-sourceon top of that function and another, playlist-id, that takes an AllegroServe request object and returns the appropriate playlist identifier. The find-song-sourcefunction is also where you grab the User-Agent string out of the request object and stash it in the playlist object.

(defmethod find-song-source ((type (eql 'playlist)) request)

(let ((playlist (lookup-playlist (playlist-id request))))

(with-playlist-locked (playlist)

(let ((user-agent (header-slot-value request :user-agent)))

(when user-agent (setf (user-agent playlist) user-agent))))

playlist))

The trick, then, is how you implement playlist-id, the function that extracts the identifier from the request object. You have a couple options, each with different implications for the user interface. You can pull whatever information you want out of the request object, but however you decide to identify the client, you need some way for the user of the Web interface to get hooked up to the right playlist.

For now you can take an approach that "just works" as long as there's only one MP3 client per machine connecting to the server and as long as the user is browsing the Web interface from the machine running the MP3 client: you'll use the IP address of the client machine as the identifier. This way you can find the right playlist for a request regardless of whether the request is from the MP3 client or a Web browser. You will, however, provide a way in the Web interface to select a different playlist from the browser, so the only real constraint this choice puts on the application is that there can be only one connected MP3 client per client IP address. [307] This approach also assumes that every client machine has a unique IP address. This assumption should hold as long as all the users are on the same LAN but may not hold if clients are connecting from behind a firewall that does network address translation. Deploying this application outside a LAN will require some modifications, but if you want to deploy this application to the wider Internet, you'd better know enough about networking to figure out an appropriate scheme yourself. The implementation of playlist-idlooks like this:

(defun playlist-id (request)

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Practical Common Lisp»

Представляем Вашему вниманию похожие книги на «Practical Common Lisp» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Отзывы о книге «Practical Common Lisp»

Обсуждение, отзывы о книге «Practical Common Lisp» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x