Browse files

implement track iterator

  • Loading branch information...
1 parent af9a961 commit 8be470e5509ed2971c6222c159561cdf1efc41af @vilhelmk committed Oct 25, 2011
Showing with 242 additions and 88 deletions.
  1. +7 −54 album.c
  2. +1 −1 config.m4
  3. +11 −0 php_spotify.h
  4. +10 −33 playlist.c
  5. +1 −0 spotify.c
  6. +212 −0 trackiterator.c
View
61 album.c
@@ -27,8 +27,6 @@ OTHER DEALINGS IN THE SOFTWARE.
zend_class_entry *spotifyalbum_ce;
-PHP_METHOD(SpotifyAlbum, browse);
-
PHP_METHOD(SpotifyAlbum, __construct)
{
zval *object = getThis();
@@ -43,7 +41,6 @@ PHP_METHOD(SpotifyAlbum, __construct)
spotifyalbum_object *obj = (spotifyalbum_object*)zend_object_store_get_object(object TSRMLS_CC);
obj->session = p->session;
obj->album = album;
- obj->albumbrowse = NULL;
zend_update_property(spotifyalbum_ce, getThis(), "spotify", strlen("spotify"), parent TSRMLS_CC);
@@ -53,11 +50,6 @@ PHP_METHOD(SpotifyAlbum, __construct)
PHP_METHOD(SpotifyAlbum, __destruct)
{
spotifyalbum_object *obj = (spotifyalbum_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- if (obj->albumbrowse != NULL) {
- sp_albumbrowse_release(obj->albumbrowse);
- }
-
sp_album_release(obj->album);
}
@@ -103,36 +95,21 @@ PHP_METHOD(SpotifyAlbum, getArtist)
PHP_METHOD(SpotifyAlbum, getNumTracks)
{
- zval tempretval, *thisptr = getThis();
- spotifyalbum_object *p = (spotifyalbum_object*)zend_object_store_get_object(thisptr TSRMLS_CC);
- SPOTIFY_METHOD(SpotifyAlbum, browse, &tempretval, thisptr);
- RETURN_LONG(sp_albumbrowse_num_tracks(p->albumbrowse));
+ zend_throw_exception(zend_exception_get_default(), "SpotifyAlbum::getNumTracks() is deprecated. See SpotifyAlbum::getTracks().");
}
PHP_METHOD(SpotifyAlbum, getTracks)
{
- int num_tracks, i;
- zval tempretval, *thisptr = getThis(), *spotifyobject;
-
- spotifyalbum_object *p = (spotifyalbum_object*)zend_object_store_get_object(thisptr TSRMLS_CC);
+ zval tempretval, *type, *spotifyobject;
- SPOTIFY_METHOD(SpotifyAlbum, browse, &tempretval, thisptr);
+ ALLOC_INIT_ZVAL(type);
+ Z_TYPE_P(type) = IS_LONG;
+ Z_LVAL_P(type) = 1;
spotifyobject = GET_THIS_PROPERTY(spotifyalbum_ce, "spotify");
- array_init(return_value);
-
- num_tracks = sp_albumbrowse_num_tracks(p->albumbrowse);
-
- for (i=0; i<num_tracks; i++) {
- sp_track *track = sp_albumbrowse_track(p->albumbrowse, i);
-
- zval *z_track;
- ALLOC_INIT_ZVAL(z_track);
- object_init_ex(z_track, spotifytrack_ce);
- SPOTIFY_METHOD2(SpotifyTrack, __construct, &tempretval, z_track, spotifyobject, track);
- add_next_index_zval(return_value, z_track);
- }
+ object_init_ex(return_value, spotifytrackiterator_ce);
+ SPOTIFY_METHOD3(SpotifyTrackIterator, __construct, &tempretval, return_value, getThis(), type, spotifyobject);
}
PHP_METHOD(SpotifyAlbum, getType)
@@ -147,29 +124,6 @@ PHP_METHOD(SpotifyAlbum, __toString)
RETURN_STRING(sp_album_name(p->album), 1);
}
-static void albumbrowse_complete(sp_albumbrowse *result, void *userdata)
-{
- spotifyalbum_object *p = (spotifyalbum_object*)userdata;
- p->albumbrowse = result;
-}
-
-PHP_METHOD(SpotifyAlbum, browse)
-{
- int timeout = 0;
-
- spotifyalbum_object *p = (spotifyalbum_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
- if (p->albumbrowse != NULL) {
- RETURN_TRUE;
- }
-
- sp_albumbrowse *tmpbrowse = sp_albumbrowse_create(p->session, p->album, albumbrowse_complete, p);
- while (!sp_albumbrowse_is_loaded(tmpbrowse)) {
- sp_session_process_events(p->session, &timeout);
- }
-
- RETURN_TRUE;
-}
-
function_entry spotifyalbum_methods[] = {
PHP_ME(SpotifyAlbum, __construct, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR)
PHP_ME(SpotifyAlbum, __destruct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
@@ -180,7 +134,6 @@ function_entry spotifyalbum_methods[] = {
PHP_ME(SpotifyAlbum, getNumTracks, NULL, ZEND_ACC_PUBLIC)
PHP_ME(SpotifyAlbum, getTracks, NULL, ZEND_ACC_PUBLIC)
PHP_ME(SpotifyAlbum, getType, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(SpotifyAlbum, browse, NULL, ZEND_ACC_PRIVATE)
PHP_ME(SpotifyAlbum, __toString, NULL, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
View
2 config.m4
@@ -4,5 +4,5 @@ if test "$PHP_SPOTIFY" = "yes"; then
AC_DEFINE(HAVE_SPOTIFY, 1, [Whether you have Spotify])
LDFLAGS="$LDFLAGS -lspotify"
PHP_ADD_LIBRARY_WITH_PATH(spotify, "", SPOTIFY_SHARED_PATH)
- PHP_NEW_EXTENSION(spotify, spotify.c playlist.c track.c artist.c album.c user.c albumiterator.c, $ext_shared)
+ PHP_NEW_EXTENSION(spotify, spotify.c playlist.c track.c artist.c album.c user.c albumiterator.c trackiterator.c, $ext_shared)
fi
View
11 php_spotify.h
@@ -91,6 +91,16 @@ typedef struct {
} spotifyuser_object;
typedef struct {
+ zend_object std;
+ sp_session *session;
+ int type;
+ sp_albumbrowse *albumbrowse;
+ sp_playlist *playlist;
+ int length;
+ int position;
+} spotifytrackiterator_object;
+
+typedef struct {
sp_session *session;
zval *obj;
} container_browse_data;
@@ -110,6 +120,7 @@ extern zend_class_entry *spotifyalbum_ce;
extern zend_class_entry *spotifyuser_ce;
extern zend_class_entry *spotifyalbumiterator_ce;
+extern zend_class_entry *spotifytrackiterator_ce;
extern void get_playlistcontainer_playlists(zval *return_value, container_browse_data *p, sp_playlistcontainer *pc);
View
43 playlist.c
@@ -80,30 +80,16 @@ PHP_METHOD(SpotifyPlaylist, getURI)
PHP_METHOD(SpotifyPlaylist, getTracks)
{
- int i, num_tracks, timeout = 0;
- zval *thisptr = getThis(), tempretval, *parent, *spotifyobject;
- spotifyplaylist_object *p = (spotifyplaylist_object*)zend_object_store_get_object(thisptr TSRMLS_CC);
-
- spotifyobject = zend_read_property(spotifyplaylist_ce, thisptr, "spotify", strlen("spotify"), NOISY TSRMLS_CC);
-
- SPOTIFY_METHOD(SpotifyPlaylist, browse, &tempretval, thisptr);
+ zval tempretval, *type, *spotifyobject;
- array_init(return_value);
+ ALLOC_INIT_ZVAL(type);
+ Z_TYPE_P(type) = IS_LONG;
+ Z_LVAL_P(type) = 0;
- num_tracks = sp_playlist_num_tracks(p->playlist);
- for (i=0; i<num_tracks; i++) {
- sp_track *track = sp_playlist_track(p->playlist, i);
- while (!sp_track_is_loaded(track)) {
- sp_session_process_events(p->session, &timeout);
- }
+ spotifyobject = GET_THIS_PROPERTY(spotifyplaylist_ce, "spotify");
- zval *z_track;
- ALLOC_INIT_ZVAL(z_track);
- object_init_ex(z_track, spotifytrack_ce);
- SPOTIFY_METHOD2(SpotifyTrack, __construct, &tempretval, z_track, spotifyobject, track);
-
- add_next_index_zval(return_value, z_track);
- }
+ object_init_ex(return_value, spotifytrackiterator_ce);
+ SPOTIFY_METHOD3(SpotifyTrackIterator, __construct, &tempretval, return_value, getThis(), type, spotifyobject);
}
PHP_METHOD(SpotifyPlaylist, getOwner)
@@ -126,6 +112,9 @@ PHP_METHOD(SpotifyPlaylist, getDescription)
RETURN_STRING(sp_playlist_get_description(p->playlist), 1);
}
+/**
+ * XXX: candidate to be deprecated, better use is the track iterator's count() function.
+ */
PHP_METHOD(SpotifyPlaylist, getNumTracks)
{
spotifyplaylist_object *p = (spotifyplaylist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
@@ -266,17 +255,6 @@ PHP_METHOD(SpotifyPlaylist, removeTrack)
}
}
-PHP_METHOD(SpotifyPlaylist, browse)
-{
- int timeout = 0;
-
- spotifyplaylist_object *p = (spotifyplaylist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- while (!sp_playlist_is_loaded(p->playlist)) {
- sp_session_process_events(p->session, &timeout);
- }
-}
-
PHP_METHOD(SpotifyPlaylist, __toString)
{
spotifyplaylist_object *p = (spotifyplaylist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
@@ -299,7 +277,6 @@ function_entry spotifyplaylist_methods[] = {
PHP_ME(SpotifyPlaylist, rename, NULL, ZEND_ACC_PUBLIC)
PHP_ME(SpotifyPlaylist, addTrack, NULL, ZEND_ACC_PUBLIC)
PHP_ME(SpotifyPlaylist, removeTrack, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(SpotifyPlaylist, browse, NULL, ZEND_ACC_PRIVATE)
PHP_ME(SpotifyPlaylist, __toString, NULL, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
View
1 spotify.c
@@ -418,6 +418,7 @@ PHP_MINIT_FUNCTION(spotify)
spotify_init_user(TSRMLS_C);
spotify_init_albumiterator(TSRMLS_C);
+ spotify_init_trackiterator(TSRMLS_C);
return SUCCESS;
}
View
212 trackiterator.c
@@ -0,0 +1,212 @@
+/*
+Copyright (c) 2011 Vilhelm K. Vardøy, vilhelmkv@gmail.com
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "php_spotify.h"
+#include <zend_interfaces.h>
+
+zend_class_entry *spotifytrackiterator_ce;
+
+#define TYPE_ALBUM 1
+#define TYPE_PLAYLIST 0
+
+void spotify_albumbrowse_complete(sp_albumbrowse *result, void *userdata) {
+
+}
+
+PHP_METHOD(SpotifyTrackIterator, __construct)
+{
+ zval *thisptr = getThis(), *parent, *spotifyobject, *type;
+ spotifytrackiterator_object *obj;
+ spotifyalbum_object *albumobj;
+ spotifyplaylist_object *playlistobj;
+ int timeout = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzO", &parent, &type, &spotifyobject, spotify_ce) == FAILURE) {
+ return;
+ }
+
+ obj = (spotifytrackiterator_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+ obj->position = 0;
+ obj->type = Z_LVAL_P(type);
+
+ if (obj->type < 0 || obj->type > 1) {
+ zend_throw_exception(zend_exception_get_default(), "SpotifyTrackIterator::__construct() type is invalid.");
+ return;
+ }
+
+ switch (obj->type) {
+ case TYPE_ALBUM:
+ albumobj = (spotifyalbum_object*)zend_object_store_get_object(parent TSRMLS_CC);
+ obj->session = albumobj->session;
+ obj->albumbrowse = sp_albumbrowse_create(obj->session, albumobj->album, spotify_albumbrowse_complete, obj);
+
+ while (!sp_albumbrowse_is_loaded(obj->albumbrowse)) {
+ sp_session_process_events(obj->session, &timeout);
+ }
+
+ obj->length = sp_albumbrowse_num_tracks(obj->albumbrowse);
+ sp_albumbrowse_add_ref(obj->albumbrowse);
+ break;
+
+ case TYPE_PLAYLIST:
+ playlistobj = (spotifyplaylist_object*)zend_object_store_get_object(parent TSRMLS_CC);
+ obj->session = playlistobj->session;
+ obj->playlist = playlistobj->playlist;
+ obj->length = sp_playlist_num_tracks(obj->playlist);
+
+ sp_playlist_add_ref(obj->playlist);
+ break;
+ }
+
+ zend_update_property(spotifytrackiterator_ce, getThis(), "spotify", strlen("spotify"), spotifyobject TSRMLS_CC);
+}
+
+PHP_METHOD(SpotifyTrackIterator, __destruct)
+{
+ spotifytrackiterator_object *p = (spotifytrackiterator_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ switch (p->type) {
+ case TYPE_ALBUM:
+ sp_albumbrowse_release(p->albumbrowse);
+ break;
+ case TYPE_PLAYLIST:
+ sp_playlist_release(p->playlist);
+ break;
+ }
+}
+
+PHP_METHOD(SpotifyTrackIterator, current)
+{
+ spotifytrackiterator_object *p;
+ sp_track *track;
+ zval temp, *spotifyobject;
+
+ p = (spotifytrackiterator_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ switch (p->type) {
+ case TYPE_ALBUM:
+ track = sp_albumbrowse_track(p->albumbrowse, p->position);
+ break;
+ case TYPE_PLAYLIST:
+ track = sp_playlist_track(p->playlist, p->position);
+ break;
+ default:
+ zend_throw_exception(zend_exception_get_default(), "SpotifyTrackIterator::current() invalid type", 0 TSRMLS_CC);
+ return;
+ }
+
+ spotifyobject = GET_THIS_PROPERTY(spotifytrackiterator_ce, "spotify");
+
+ object_init_ex(return_value, spotifytrack_ce);
+ SPOTIFY_METHOD2(SpotifyTrack, __construct, &temp, return_value, spotifyobject, track);
+}
+
+PHP_METHOD(SpotifyTrackIterator, key)
+{
+ spotifytrackiterator_object *p = (spotifytrackiterator_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+ RETURN_LONG(p->position);
+}
+
+PHP_METHOD(SpotifyTrackIterator, next)
+{
+ spotifytrackiterator_object *p = (spotifytrackiterator_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+ p->position++;
+}
+
+PHP_METHOD(SpotifyTrackIterator, rewind)
+{
+ spotifytrackiterator_object *p = (spotifytrackiterator_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+ p->position = 0;
+}
+
+PHP_METHOD(SpotifyTrackIterator, valid)
+{
+ spotifytrackiterator_object *p = (spotifytrackiterator_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+ if (p->position >= p->length) {
+ RETURN_FALSE;
+ } else {
+ RETURN_TRUE;
+ }
+}
+
+PHP_METHOD(SpotifyTrackIterator, count)
+{
+ spotifytrackiterator_object *p = (spotifytrackiterator_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+ RETURN_LONG(p->length);
+}
+
+function_entry spotifytrackiterator_methods[] = {
+ PHP_ME(SpotifyTrackIterator, __construct, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR)
+ PHP_ME(SpotifyTrackIterator, __destruct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
+ PHP_ME(SpotifyTrackIterator, current, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(SpotifyTrackIterator, key, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(SpotifyTrackIterator, next, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(SpotifyTrackIterator, rewind, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(SpotifyTrackIterator, valid, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(SpotifyTrackIterator, count, NULL, ZEND_ACC_PUBLIC)
+ {NULL, NULL, NULL}
+};
+
+void spotifytrackiterator_free_storage(void *object TSRMLS_DC)
+{
+ spotifytrackiterator_object *obj = (spotifytrackiterator_object*)object;
+ zend_hash_destroy(obj->std.properties);
+ FREE_HASHTABLE(obj->std.properties);
+ efree(obj);
+}
+
+zend_object_value spotifytrackiterator_create_handler(zend_class_entry *type TSRMLS_DC)
+{
+ zval *tmp;
+ zend_object_value retval;
+
+ spotifytrackiterator_object *obj = (spotifytrackiterator_object *)emalloc(sizeof(spotifytrackiterator_object));
+ memset(obj, 0, sizeof(spotifytrackiterator_object));
+
+ zend_object_std_init(&obj->std, type TSRMLS_CC);
+ zend_hash_copy(obj->std.properties, &type->default_properties,
+ (copy_ctor_func_t)zval_add_ref, (void *)&tmp, sizeof(zval *));
+
+ retval.handle = zend_objects_store_put(obj, NULL,
+ spotifytrackiterator_free_storage, NULL TSRMLS_CC);
+ retval.handlers = &spotify_object_handlers;
+
+ return retval;
+}
+
+void spotify_init_trackiterator(TSRMLS_D)
+{
+ zend_class_entry ce;
+ INIT_CLASS_ENTRY(ce, "SpotifyTrackIterator", spotifytrackiterator_methods);
+ spotifytrackiterator_ce = zend_register_internal_class(&ce TSRMLS_CC);
+ spotifytrackiterator_ce->create_object = spotifytrackiterator_create_handler;
+
+ zend_class_implements(spotifytrackiterator_ce TSRMLS_CC, 1, zend_ce_iterator);
+
+ zend_declare_class_constant_long(spotifytrackiterator_ce, "TYPE_PLAYLIST", strlen("TYPE_PLAYLIST"), 0 TSRMLS_CC);
+ zend_declare_class_constant_long(spotifytrackiterator_ce, "TYPE_ALBUM", strlen("TYPE_ALBUM"), 1 TSRMLS_CC);
+
+ zend_declare_property_null(spotifytrackiterator_ce, "spotify", strlen("spotify"), ZEND_ACC_PROTECTED TSRMLS_CC);
+}

0 comments on commit 8be470e

Please sign in to comment.