GithubHelp home page GithubHelp logo

plangular's Introduction

⚠️ This repo is no longer being maintained

For creating custom SoundCloud players, I highly recommend react-soundplayer or for a more general solution, see plyr.

Plangular

Angular directive for custom SoundCloud players jxnblk.com/plangular

Getting Started

npm install plangular-3

Or install with Bower:

bower install plangular

Or use the CDN:

<script src="http://d2v52k3cl9vedd.cloudfront.net/plangular/3.1.0/plangular.min.js"></script>

Angular app

Include a link to plangular after including Angular.

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script src="bower_components/plangular/dist/plangular.min.js"></script>

Initialize the app

Configure Plangular with your own client_id. For new SoundCloud apps, you can register at https://developers.soundcloud.com/

<body ng-app="app">

  <script>
    var app = angular.module('app', ['plangular'])
      .config(function(plangularConfigProvider){
        plangularConfigProvider.clientId = '[YOUR-CLIENT-ID]';
      });
  </script>
</body>

Create a plangular directive instance

<div plangular="http://soundcloud.com/jxnblk/plangular">
</div>

Include track info

<div plangular="http://soundcloud.com/jxnblk/plangular">
  <h3>{{track.user.username}} - {{track.title}}</h3>
  <a ng-href="{{track.permalink_url}}">View on SoundCloud</a>
</div>

Add player controls

<button ng-click="playPause()">Play/Pause</button>

Or with separate play/pause controls:

<button ng-click="play()">Play</button>
<button ng-click="pause()">Pause</button>

Show current time and duration

Use the hhmmss filter to format seconds as hh:mm:ss strings.

<small>{{ currentTime | hhmmss }} | {{ duration | hhmmss }}</small>

Progress bar

<progress ng-value="currentTime / duration || 0">
  {{ currentTime / duration || 0 }}
</progress>

Add scrubber functionality

<progress
  ng-click="seek($event)"
  ng-value="currentTime / duration">
  {{ currentTime / duration }}
</progress>

Add images

<img ng-src="{{ track.artwork_url  }}" alt="{{ track.title }}" />
<img ng-src="{{ track.waveform_url }}" alt="waveform" />

Note: The waveform image that the SoundCloud API provides is a 1200 x 280px PNG with a light gray frame and transparent middle. To show progress use absolute positioning with the waveform in front. The light gray color is #efefef.

Loading states

Use the ng-if directive to show and hide content based on whether the track has loaded.

<div ng-if="!track"><!-- Loading state --></div>
<div ng-if="track"><!-- Player --></div>

Playlists

Use the tracks array and ng-repeat when using a SoundCloud playlist. Pass the $index to the playPause() method to trigger playback on a per-track basis. Determine which track is currently playing with player.playing === track.src.

<ul>
  <li ng-repeat="track in tracks">
    <button
      ng-click="playPause($index)"
      ng-class="{'active': player.playing === track.src}">
      {{track.user.username}} - {{track.title}}
    </button>
  </li>
</ul>

User tracks

To load the most recent tracks from a given user, use the tracks endpoint. Use ng-repeat to iterate over the tracks array.

<div plangular="http://soundcloud.com/jxnblk/tracks">
</div>

User likes

To load the most recent likes from a given user, use the likes endpoint.

<div plangular="http://soundcloud.com/jxnblk/likes">
</div>

Previous/next controls

To skip to the next and previous track in a playlist or array of tracks, use the previous() and next() methods.

<button ng-click="previous()">Previous</button>
<button ng-click="next()">Next</button>

Example templates

See more examples and starter templates in docs/examples


API

track

Object returned from the SoundCloud API

tracks

An array of track objects if the instance is a playlist or list of tracks

player

Audio player object

audio

The HTML5 <audio> element used by the player, exposed for access to media events.

currentTime

Angular-friendly currentTime from the audio element

duration

Angular-friendly duration from the audio element. Note: you can also access duration in milliseconds from the SoundCloud track object.

index

Currently playing track index in a playlist or other array of tracks.

playlist

Cloned object of track if track.tracks exists. This is useful for displaying the title of the playlist.

play(i)

Plays the track. Optionally pass an index when handling playlists.

pause()

Pauses the player.

playPause(i)

Toggles playback. Optionally pass an index when handling playlists.

previous()

Skip to previous track when handling playlists

next()

Skip to next track when handling playlists

seek($event)

Sets the audio element’s currentTime property based on a pointer event.


Using the SoundCloud API

Track object

For more details on the SoundCloud track object, see https://developers.soundcloud.com/docs/api/reference#tracks

Terms

According to the SoundCloud API terms you must:

  • Credit the user as the creator of the content
  • Credit SoundCloud as the source
  • Include a link to the sound on SoundCloud (i.e. a link using track.permalink_url)

Read more here: http://developers.soundcloud.com/docs/api/terms-of-use

Troubleshooting

SoundCloud provides an option for users to prevent streaming to third-party apps. If your sound isn't playing check the track.streamable variable. If it's set to false, there is no way to play that sound with the API.

plangular's People

Contributors

antonagestam avatar jxnblk avatar loganarnett avatar matheusabr avatar samuelcole avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

plangular's Issues

'plangular' attribute is not observed

If the plangular attribute is assigned like so...

<div plangular="{{myURL}}" > 

and the property 'myURL' changes, or in my case isn't available until the render is finished, the directive doesn't work. Is there a work-around to this?

Alternative to playPause(i) for filtering purposes?

Hey,

I am trying to filter a playlist, but as a result the index doesn't follow up and playPause($index) triggers the wrong tracks. I tried passing the track object instead: playPause(track) or playPause(track.src) as pointed out here http://codeutopia.net/blog/2014/11/10/angularjs-best-practices-avoid-using-ng-repeats-index/

However it doesn't seem to work and the console shows Cannot read property 'src' of undefined
I assume plangular is not coded with filtering in mind or am I doing something wrong?

My filter looks like this
<div ng-repeat="track in tracks | filter:{ title: 'XXX' }">
(the filtering part works)

Best,
shazzy

Using Plangular without Soundcloud

Hello,

Great player and great code. I am looking to use your player, but with MP3s. Is that possible? I have an API (/tracks.json) that I am pulling the song data from for my site. I have tried to rework some of the code so that the plangular attribute (src) is the mp3 file url which on the html is being generated by an ng-repeat that is pulling from the API. So my quick question is what would need to change to bypass the soundcloud api get, and just use the mp3 file url as the src?

Thanks,
John

Play/Pause Event Handlers

First of all, thanks for this awesome project!!

I'm new to Vue.js.. and was wondering if there was any way to bind an event handler to play or pause events?

Non-hosted plangular app looks for incorrect api endpoint

I'm currently writing an angular web app, that when finished it would not be hosted on the web but instead be ran from their computers.

If you try to run plangular from a file, it will be unable to contact the soundcloud api, as it assumes that the soundcloud api is a file on your computer

GET file://api.soundcloud.com/resolve.json?callback=angular.callbacks._1&client…3361983f16d2527b01fbf6408b7d7&url=http:%2F%2Fsoundcloud.com%2Fmrsjxn%2Fbbb net::ERR_FILE_NOT_FOUND 

To replicate, download master as a zip file, extract and run in your browser. Tested in both Chrome and Firefox

Automatic play ?

Hi !

Thanks for your angular way to use soundcloud api (i love your way of doing it !)

Anyway i'd like to automatically launch the player at the first load of my page (plangularPlayerService ? in the directive parameters "plangular-autoplay" ? "autoplay" ?).

I'll try to find a weird way to do so, but i'd really love to have a simple way to achieve that.

Thanks,
Okazari

Global Player feature

Hey,
the v3 update breaks the global player functionality for me. Are there plans to include this feature in v3 or should I stick to v2?

Thank you so much for developing this btw! It has easily become my favorite custom SC solution!
Best, shazzy

Seek not working in FireFox

Hi,

Currently there is an issue in FireFox with Plangular which doesn't allow you to seek in a track. The error is: "Error: Value being assigned to HTMLMediaElement.currentTime is not a finite floating-point value"

The error also occurs on the example page of Plangular itself.

Any idea how to solve this?

Thanks.

plangular_error

Including the 'Buy' button

I could hard-code this, but do you have plans to include Soundcloud's 'Buy' button in the player? As a sidenote, I'm really impressed with this project! Thanks for putting it out there.

Jekyll strips out plangular tags

Jekyll uses liquid converters so it strips out the plangular tags. You have to escape them either at the beginning and end of the document with {% raw  %} and {% endraw %} or if you are using liquid tags in a bunch of places you can escape the individual tags like this:
{{ "{{ track.user.username " }}}}

Here's a stack overflow article about it http://stackoverflow.com/questions/3426182/how-to-escape-liquid-template-tags - not sure if there is a better way but this works.

Parse API responses pre-processed externally

Love Plangular. Used it in a webapp I'm working on. The app uses Soundcloud's PHP API Wrapper to pull data from tracks. That means I'm essentially doubling the number of calls I'm making to the API by passing the permalink to Plangular when I could just straight pass meta that I've already pulled over cURL.

Your code is a doozy, and my lack of knowledge of how Vuejs works meant it blew my mind and I couldn't hack my way around the source to pass the Stream_URL.

Can you add some sort of support for external data sources being passed to the player to reduce calls to the API?

Cheers,

Greg

Updating current track title in playlist

Hi how can I get the current playing track from the playlist example - not the playlist title.

Just using {{ track.title }} doesn't do anything. Any easy way to do this without lots of js?

Thanks

Autoplay?

Is there an autoplay setting?

And thank you for creating this project. A really great player.

Progress bar doesn't play nicely with Firefox

Hi,

So I've styled the progress bar with a background image of the waveform using an inline stylesheet

progress::-webkit-progress-bar

I've then styled progress::-webkit-progress-value with a background colour to show progress. Obviously these are webkit specific CSS directives.

In Firefox, I couldn't find a CSS selector to achieve the same effect. Also, click to seek doesn't work for me in Firefox either.

So -

  • Can you style the progress bar the same way in Firefox?
  • Should Click to seek work in Firefox?

Here's the code I'm using

<div class="custom-player" v-if="player.playing == track">
    <progress class="progressbar full-width" v-on="click: player.seek($event)" value="{{ currentTime / duration || 0 }}">
        {{ currentTime / duration }}
    </progress>
</div>
<div class="custom-player" v-if="player.playing != track" v-on="click: play()">
    <progress class="progressbar full-width" v-on="click: player.seek($event)" value="{{ currentTime / duration || 0 }}">
        {{ currentTime / duration }}
    </progress>
</div>

I've done this to get the "click on waveform to play" effect, and this was the way I managed to get it to play nice with the play button and such. Just adding the on click event on its own was causing "stream_url undefined" issues.

Cheers,

Greg

Safari 7.0

Hi, first of all very nice plug ;)
I'm using it for a new project and it works like a charm on Chrome & Firefox (Mac with Mavericks) but nothing work with Safari 7.0 (neither safari mobile).

I have readed on google some topics with angularjs and Safari but I couldn't found a solution, seems to be a problem with that and not with your code but I'm not sure so I posted here.

Thanks!

502 when access Soundcloud API

Hi, I know that this is not an issue with the library. But do you have any idea what is going on with SoundCloud API? Whenever I touch the API, I failed into errors like this:

502 Error

There is some occasions that it's ok for retrieving the Song information. After that, I got another 500 error when accessing the stream_url.

Damn!!

Method to reinitalize plangular from view

Hey man,

Is there a way that I can reinit plangular to pull new data from Soundcloud in without changing view, playlists or reloading please?

I've hacked it so far that I can be notified in the directive if it needs to reload, but cannot actually reload it.

E.g. the trackData permalink changes in the scope in the view, but plangular does not update.

What would you recommend please?

Thanks

  scope.$on('trackDataChange', function(e, trackData){
      console.log('change in directive');
      plangular.init();
    });

v2

  • README update
  • Examples section with markup
  • CDN Links
  • Download links
  • Autobass
  • [ ] Keyboard shortcut documentation

Pulling all/latest soundcloud tracks?

Hi,

kinda new to github, but is there a way to pull like all of a users tracks in one go but have them as seperate tracks on the website. So like it is now I can pull a track but is there a way to pull them all automatically and then display as multiple tracks.

hope someone understands. Calvin.

Docs

  • CSS tips
  • player object vs track

Can't pass in track urls as variables

<li ng-repeat="data in tracks">
<div plangular data-src="{{data}}">
</li>

I want to iterate over an array of tracks and display them with plangular. Reading up on directives, it sounds like there are scope issues with doing this. Any suggestions on what to do?

Semi continuous playback

Hi, I am looking into your solution and it seems very nice, but I have a question. I know that continous playback is not possible without involving AJAX or without using a popup window, but I would like to know if it is possible save the position inside the track and when a new page is loaded after a short break start again to play the track from the second it was.

Thank you in advance for the answer

Fixed seek for FF

Issue:

Seek does not work in FF.

Reproduce:

Attempt to seek in FF does not work.

Fix:

philhudson91:patch-2

Won't update upon updating URL

Here is my code:

<div ng-repeat="url in darude track by $index">
<div plangular="{{url}}">
  <p>{{ track.user.username }}</p>
  <h1>{{ track.title }}</h1>
  <button ng-click="playPause()">Play/Pause</button>
  <!-- or -->
  <button ng-click="play()" ng-if="player.playing != track">Play</button>
  <button ng-click="pause()" ng-if="player.playing == track">Pause</button>

</div>

When ever I try and update the URL value the player will not update as well.

Can I list all comments below the player?

I want to list the comments vertically in a table below the playing track, such that clicking the comment will advance the player to the time of the comment.

Also, I would like the option to turn on/off autoplay from that point forward.

Thanks,
Martin.

Now playing when not using v-repeat

Hi,

I'm outputting a tracklist on a playlist with PHP so I can get individual data on each track (mainly to see if the user has liked the track before). I can't work out the syntax to add a class for "Now Playing"

This is the code I'm using

<div class="trackstuff">
    <div class="titlebox">
        <h4 class="artist"><a href="<?php echo $trackmetadata['artist_permalink_url']; ?>" target="_blank"><?php echo htmlentities($trackmetadata['artist_username']); ?></a></h4>
        <h3 class="tracktitle"><a href="<?php echo $trackmetadata['permalink_url']; ?>" target="_blank"><?php echo htmlentities($trackmetadata['title']); ?></a></h3>
    </div>

   <div class="pghold progresscontain" v-if="player.tracks[player.i] != track || !player.playing" v-on="click: playPause(player.playlistIndex)">
        <div class="progressbase"></div>
        <div class="progressbar" v-style="width: (currentTime / duration * 100) + '%'"></div>
        <div class="seeker"></div>
   </div>
   <div class="progresscontain" v-if="player.tracks[player.i] == track && player.playing" v-on="click: seek($event)">
        <div class="progressbase"></div>
        <div class="progressbar" v-style="width: (currentTime / duration * 100) + '%'"></div>
        <div class="seeker"></div>  
    </div>
    <div class="waveform" style="background-image:url({{ player.currentTrack.waveform_url }}); display:none;" v-if="player.tracks[player.i] == track && player.playing" v-class="'showme'"></div>
    <div class="waveform coverhold" style="background-image:url(<?php echo str_replace('large.jpg','t500x500.jpg',$trackmetadata['artworkuse']); ?>);" v-if="player.tracks[player.i] != track || !player.playing"></div>
    <div class="waveform covercover" v-if="player.tracks[player.i] != track || !player.playing"></div>

    <div class="durationcontain"><span class="starttime" v-on="click:return false">{{ currentTime | prettyTime }}</span>
    <span class="duration" v-on="click:return false">{{ duration | prettyTime }}</span></div>
</div>
<ul class="playlist-tracklist">
<?php $i = 0; foreach($trackmetadata['tracks'] as $playlistitem) : ?>
 <li class="tracklist-item"><a href="javascript:void(0)" id="playlist-item-<?php echo $i+1; ?>" class="playlist-item" v-on="click: playPause(<?php echo $i; ?>);"  v-class="player.currentTrack == tracks.<?php echo $i; ?> ? 'now-playing' : ''">
  <span class="trackno"><?php echo $i+1; ?>.</span>
  <span class="artist"><?php echo htmlentities($playlistitem->user->username);?></span> - <span class="tracktitle"><?php echo htmlentities($playlistitem->title);?></span>
</a> 
<div class="submeta">
    <div class="metaitem"><a href="<?php echo $playlistitem->permalink_url; ?>" target="_blank" class="awesome nssc soundcloudlink" title="Listen to <?php echo htmlentities($playlistitem->title); ?> on Soundcloud"><i class="fa fa-soundcloud"></i></a></div>
    <?php if(!$playlistitem->user_favorite) : ?><div class="metaitem"><a href="javascript:void(0)" onclick="nsscLike(<?php echo $playlistitem->id; ?> ,this,'like');" class="awesome nssc likebutton" title="Favourite <?php echo htmlentities($playlistitem->title); ?>"><i class="fa fa-heart-o"></i></a></div><?php endif; ?>
    <?php if($playlistitem->user_favorite) : ?><div class="metaitem"><a href="javascript:void(0)" onclick="nsscLike(<?php echo $playlistitem->id; ?>,this,'unlike');" class="awesome nssc likebutton liked" title="Favourite <?php echo htmlentities($playlistitem->title);?>"><i class="fa fa-heart"></i></a></div><?php endif; ?>
    <?php if($playlistitem->commentable) : ?><div class="metaitem"><a href="javascript:void(0)" onclick="nsscComment(<?php echo $playlistitem->id; ?>,this);" class="awesome nssc commentbutton" title="Comment on <?php echo htmlentities($playlistitem->title); ?>"><i class="fa fa-comment"></i></a></div><?php endif; ?>
    <?php if($playlistitem->downloadable) : ?><div class="metaitem"><a href="https://api.soundcloud.com/tracks/<?php echo $playlistitem->id; ?>/download?client_id=<?php echo SC_CLIENT_ID; ?>" class="awesome nssc downloadbutton" title="Download <?php echo htmlentities($playlistitem->title); ?>"><i class="fa fa-cloud-download"></i></a></div><?php endif; ?>
    <?php if($playlistitem->purchase_url) : ?><div class="metaitem"><a href="<?php echo $playlistitem->purchase_url; ?>" target="_blank" class="awesome nssc buynowbutton" title="<?php echo ($playlistitem->purchase_title) ? htmlentities($playlistitem->purchase_title) : 'Buy Now'; ?>"><i class="fa fa-shopping-cart"></i></a></div><?php endif; ?>
  </div></li>
<?php $i++; endforeach; ?>
</ul>

It's obviously this bit here that's not working:

v-class="player.currentTrack == tracks.<?php echo $i; ?> ? 'now-playing' : ''"

Is there a syntax that I can achieve what I want using the PHP increment rather than Vue's one?

Thanks,

Greg

plangular don't work

i use your code to my website and now it's not working.
i checked your examples and you have problem too.
so what we do now?

Using Plangular without Soundcloud

Hello,

Great player and great code. I am looking to use your player, but with MP3s. Is that possible? I have an API (/tracks.json) that I am pulling the song data from for my site. I have tried to rework some of the code so that the plangular attribute (src) is the mp3 file url which on the html is being generated by an ng-repeat that is pulling from the API. So my quick question is what would need to change to bypass the soundcloud api get, and just use the mp3 file url as the src?

Thanks

Safari: tracks with U+2028 character break player

Hey,
according to your source code comments you are aware of this issue, i would just like to extend on it from what I experienced from my testing. When the json request contains a U+2028 or U+2029 character it will break Safari. The endpoint doesn't matter, it happens on single tracks as well.

Example: https://soundcloud.com/telekollegen/telecast-002-mixed-by-jekyllandhyde
The illegal character is in front of the facebook link in the description in this case.

A possible solution is outlined in this thread- I have however no idea if it applies here since my background in programming is quite limited:

http://stackoverflow.com/questions/14179377/how-to-replace-escape-u2028-or-u2029-characters-in-php-to-stop-my-jsonp-api-br

An overview of the issue is given here:
http://timelessrepo.com/json-isnt-a-javascript-subset

edit: some more
http://stackoverflow.com/questions/2965293/javascript-parse-error-on-u2028-unicode-character/9168133#9168133

TypeError: Cannot read property 'tracks' of undefined

I'm using plangular in my app and it works fine. However, when I navigate through the page and try to play the player I get the error mention mentioned in the above. This also happens in plangular example site in the angular section. Any idea why it's doing this?

Version 3

  • Share modules between all library wrappers
  • Pass track object, audio sources, or SoundCloud URL into components, without the need to use Ajax within the component
  • Test Ractive, React, and other libraries
  • Expose audio events
  • Publish to Bower
  • Prebuilt templates

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.