Skip to content
This repository was archived by the owner on May 24, 2021. It is now read-only.

Commit c24a817

Browse files
feat(live-mode): Add live mode
1 parent 9848fda commit c24a817

20 files changed

+1446
-519
lines changed

circle.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ dependencies:
1717
- npm rebuild node-sass
1818
- gem install bundler
1919
pre:
20-
- yarn global add publish-release
20+
- echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
2121
cache_directories:
2222
- ~/.cache/yarn
2323

@@ -53,5 +53,5 @@ deployment:
5353
commands:
5454
- yarn dist:clean
5555
- yarn build
56-
- yarn deploy:release
56+
- npm publish --access public
5757
- yarn deploy:cdn

docs/live.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
---
2+
layout: page
3+
title: Live
4+
navigation: 6
5+
---
6+
7+
# Live Mode
8+
9+
<p id="example"></p>
10+
<script src="{{ 'embed.js' | relative_url }}"></script>
11+
<script>
12+
podlovePlayer('#example', {
13+
mode: 'live',
14+
title: 'Livestream',
15+
subtitle: 'Wir sind ein CreativeCommons-Webradio, das sich zur Aufgabe gemacht hat freie Musik zu verbreiten und die Hörer durch die vielen Beteiligungsmöglichkeiten direkt zu einem Teil unserer Sendungen zu machen.',
16+
link: 'https://theradio.cc',
17+
poster: 'https://theradio.cc/wp-content/uploads/2014/01/9e7d1d68285200b9d3c0-150x150.jpg',
18+
show: {
19+
title: 'TheRadio.cc',
20+
link: 'https://theradio.cc'
21+
},
22+
audio: [{
23+
url: 'http://mp3.theradio.cc/',
24+
mimeType: 'audio/mp3'
25+
}, {
26+
url: 'http://ogg.theradio.cc/',
27+
mimeType: 'audio/ogg'
28+
}]
29+
});
30+
</script>
31+
32+
## Config
33+
34+
```javascript
35+
{
36+
mode: 'live',
37+
title: 'Livestream',
38+
subtitle: 'Wir sind ein CreativeCommons-Webradio, das sich zur Aufgabe gemacht hat freie Musik zu verbreiten und die Hörer durch die vielen Beteiligungsmöglichkeiten direkt zu einem Teil unserer Sendungen zu machen.',
39+
link: 'https://theradio.cc',
40+
poster: 'https://theradio.cc/wp-content/uploads/2014/01/9e7d1d68285200b9d3c0-150x150.jpg',
41+
show: {
42+
title: 'TheRadio.cc',
43+
link: 'https://theradio.cc'
44+
},
45+
audio: [{
46+
url: 'http://mp3.theradio.cc/',
47+
mimeType: 'audio/mp3'
48+
}, {
49+
url: 'http://ogg.theradio.cc/',
50+
mimeType: 'audio/ogg'
51+
}]
52+
}
53+
```

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@
4747
"deploy:surge": "surge --project ./dist --domain podlove-player.surge.sh",
4848
"changelog": "standard-changelog"
4949
},
50+
"files": [
51+
"dist/"
52+
],
5053
"dependencies": {
5154
"babel-polyfill": "6.26.0",
5255
"bluebird": "3.5.0",
@@ -55,8 +58,7 @@
5558
"detect-browser": "1.6.2",
5659
"foundation-sites": "6.3.1",
5760
"hashcode": "1.0.3",
58-
"howler": "2.0.3",
59-
"html5-audio-driver": "0.6.3",
61+
"@podlove/html5-audio-driver": "0.6.3",
6062
"iframe-resizer": "3.5.7",
6163
"keyboardjs": "2.3.3",
6264
"lodash": "4.17.4",

scripts/deploy-release.sh

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/media/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { audio, events as audioEvents, actions as audioActions } from 'html5-audio-driver'
1+
import { audio, events as audioEvents, actions as audioActions } from '@podlove/html5-audio-driver'
22

33
export default (audioFiles) => {
44
const audioElement = audio(audioFiles)
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { get } from 'lodash'
2+
import actions from '../actions'
3+
4+
const hasChapters = chapters => chapters.length > 0
5+
const hasMeta = (show, episode) => episode.poster || show.poster || show.title || episode.title || episode.subtitle
6+
const hasFiles = files => files.length > 0
7+
8+
export default (store, action) => {
9+
switch (action.type) {
10+
case 'LOADING':
11+
store.dispatch(actions.showLoadingButton())
12+
break
13+
case 'LOADED':
14+
if (action.payload.paused) {
15+
store.dispatch(actions.showPauseButton())
16+
} else {
17+
store.dispatch(actions.showPlayingButton())
18+
}
19+
break
20+
case 'PLAY':
21+
// Default behaviour
22+
store.dispatch(actions.showPlayingButton())
23+
store.dispatch(actions.toggleProgressBar(true))
24+
store.dispatch(actions.toggleChapterControls(true))
25+
store.dispatch(actions.toggleSteppersControls(true))
26+
27+
// Error Fallbacks
28+
store.dispatch(actions.toggleInfo(true))
29+
store.dispatch(actions.toggleError(false))
30+
break
31+
case 'PAUSE':
32+
store.dispatch(actions.showPauseButton())
33+
break
34+
case 'IDLE':
35+
store.dispatch(actions.showPauseButton())
36+
store.dispatch(actions.toggleChapterControls(true))
37+
store.dispatch(actions.toggleSteppersControls(true))
38+
store.dispatch(actions.toggleProgressBar(true))
39+
break
40+
case 'INIT':
41+
const state = store.getState()
42+
const chapters = get(state, 'chapters', [])
43+
const downloadFiles = get(state, 'download.files', [])
44+
const episode = get(state, 'episode', {})
45+
const show = get(state, 'show', {})
46+
const runtime = get(state, 'runtime', {})
47+
48+
// Tabs
49+
if (hasChapters(chapters)) {
50+
store.dispatch(actions.toggleComponentTab('chapters', true))
51+
}
52+
53+
if (hasFiles(downloadFiles)) {
54+
store.dispatch(actions.toggleComponentTab('download', true))
55+
}
56+
57+
// Meta
58+
if (hasMeta(show, episode)) {
59+
store.dispatch(actions.toggleInfo(true))
60+
}
61+
62+
// Audio Modifiers
63+
if (runtime.platform === 'desktop') {
64+
store.dispatch(actions.toggleVolumeSlider(true))
65+
}
66+
67+
// Everything else without conditions
68+
store.dispatch(actions.toggleComponentTab('share', true))
69+
store.dispatch(actions.toggleComponentTab('info', true))
70+
store.dispatch(actions.toggleComponentTab('audio', true))
71+
store.dispatch(actions.toggleRateSlider(true))
72+
store.dispatch(actions.toggleInfoPoster(true))
73+
break
74+
case 'END':
75+
store.dispatch(actions.showReplayButton())
76+
break
77+
case 'ERROR_LOAD':
78+
store.dispatch(actions.toggleInfo(false))
79+
store.dispatch(actions.toggleError(true))
80+
store.dispatch(actions.showRetryButton())
81+
store.dispatch(actions.toggleProgressBar(false))
82+
store.dispatch(actions.toggleChapterControls(false))
83+
store.dispatch(actions.toggleSteppersControls(false))
84+
break
85+
case 'ERROR_MISSING_AUDIO_FILES':
86+
store.dispatch(actions.toggleInfo(false))
87+
store.dispatch(actions.toggleError(true))
88+
store.dispatch(actions.toggleButtonControl(false))
89+
store.dispatch(actions.toggleProgressBar(false))
90+
store.dispatch(actions.toggleChapterControls(false))
91+
store.dispatch(actions.toggleSteppersControls(false))
92+
break
93+
}
94+
}

src/store/effects/components.test.js renamed to src/store/effects/components.episode.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import test from 'ava'
22
import sinon from 'sinon'
33

4-
import components from './components'
4+
import components from './components.episode'
55

66
let store, state
77

src/store/effects/components.js

Lines changed: 7 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,12 @@
1-
import { get } from 'lodash'
2-
import actions from '../actions'
3-
4-
const hasChapters = chapters => chapters.length > 0
5-
const hasMeta = (show, episode) => episode.poster || show.poster || show.title || episode.title || episode.subtitle
6-
const hasFiles = files => files.length > 0
1+
import episodeComponents from './components.episode'
2+
import liveComponents from './components.live'
73

84
export default (store, action) => {
9-
switch (action.type) {
10-
case 'LOADING':
11-
store.dispatch(actions.showLoadingButton())
12-
break
13-
case 'LOADED':
14-
if (action.payload.paused) {
15-
store.dispatch(actions.showPauseButton())
16-
} else {
17-
store.dispatch(actions.showPlayingButton())
18-
}
19-
break
20-
case 'PLAY':
21-
// Default behaviour
22-
store.dispatch(actions.showPlayingButton())
23-
store.dispatch(actions.toggleProgressBar(true))
24-
store.dispatch(actions.toggleChapterControls(true))
25-
store.dispatch(actions.toggleSteppersControls(true))
26-
27-
// Error Fallbacks
28-
store.dispatch(actions.toggleInfo(true))
29-
store.dispatch(actions.toggleError(false))
30-
break
31-
case 'PAUSE':
32-
store.dispatch(actions.showPauseButton())
33-
break
34-
case 'IDLE':
35-
store.dispatch(actions.showPauseButton())
36-
store.dispatch(actions.toggleChapterControls(true))
37-
store.dispatch(actions.toggleSteppersControls(true))
38-
store.dispatch(actions.toggleProgressBar(true))
39-
break
40-
case 'INIT':
41-
const state = store.getState()
42-
const chapters = get(state, 'chapters', [])
43-
const downloadFiles = get(state, 'download.files', [])
44-
const episode = get(state, 'episode', {})
45-
const show = get(state, 'show', {})
46-
const runtime = get(state, 'runtime', {})
47-
48-
// Tabs
49-
if (hasChapters(chapters)) {
50-
store.dispatch(actions.toggleComponentTab('chapters', true))
51-
}
52-
53-
if (hasFiles(downloadFiles)) {
54-
store.dispatch(actions.toggleComponentTab('download', true))
55-
}
56-
57-
// Meta
58-
if (hasMeta(show, episode)) {
59-
store.dispatch(actions.toggleInfo(true))
60-
}
61-
62-
// Audio Modifiers
63-
if (runtime.platform === 'desktop') {
64-
store.dispatch(actions.toggleVolumeSlider(true))
65-
}
5+
const state = store.getState()
666

67-
// Everything else without conditions
68-
store.dispatch(actions.toggleComponentTab('share', true))
69-
store.dispatch(actions.toggleComponentTab('info', true))
70-
store.dispatch(actions.toggleComponentTab('audio', true))
71-
store.dispatch(actions.toggleRateSlider(true))
72-
store.dispatch(actions.toggleRateSlider(true))
73-
store.dispatch(actions.toggleInfoPoster(true))
74-
break
75-
case 'END':
76-
store.dispatch(actions.showReplayButton())
77-
break
78-
case 'ERROR_LOAD':
79-
store.dispatch(actions.toggleInfo(false))
80-
store.dispatch(actions.toggleError(true))
81-
store.dispatch(actions.showRetryButton())
82-
store.dispatch(actions.toggleProgressBar(false))
83-
store.dispatch(actions.toggleChapterControls(false))
84-
store.dispatch(actions.toggleSteppersControls(false))
85-
break
86-
case 'ERROR_MISSING_AUDIO_FILES':
87-
store.dispatch(actions.toggleInfo(false))
88-
store.dispatch(actions.toggleError(true))
89-
store.dispatch(actions.toggleButtonControl(false))
90-
store.dispatch(actions.toggleProgressBar(false))
91-
store.dispatch(actions.toggleChapterControls(false))
92-
store.dispatch(actions.toggleSteppersControls(false))
93-
break
7+
if (state.mode === 'live') {
8+
liveComponents(store, action)
9+
} else {
10+
episodeComponents(store, action)
9411
}
9512
}

src/store/effects/components.live.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { get } from 'lodash'
2+
import actions from '../actions'
3+
4+
const hasMeta = (show, episode) => episode.poster || show.poster || show.title || episode.title || episode.subtitle
5+
6+
export default (store, action) => {
7+
switch (action.type) {
8+
case 'LOADING':
9+
store.dispatch(actions.showLoadingButton())
10+
break
11+
case 'LOADED':
12+
if (action.payload.paused) {
13+
store.dispatch(actions.showPauseButton())
14+
} else {
15+
store.dispatch(actions.showPlayingButton())
16+
}
17+
break
18+
case 'PLAY':
19+
// Default behaviour
20+
store.dispatch(actions.showPlayingButton())
21+
22+
// Error Fallbacks
23+
store.dispatch(actions.toggleInfo(true))
24+
store.dispatch(actions.toggleError(false))
25+
break
26+
case 'PAUSE':
27+
store.dispatch(actions.showPauseButton())
28+
break
29+
case 'IDLE':
30+
store.dispatch(actions.showPauseButton())
31+
store.dispatch(actions.toggleChapterControls(true))
32+
store.dispatch(actions.toggleSteppersControls(true))
33+
store.dispatch(actions.toggleProgressBar(true))
34+
break
35+
case 'INIT':
36+
const state = store.getState()
37+
const episode = get(state, 'episode', {})
38+
const show = get(state, 'show', {})
39+
const runtime = get(state, 'runtime', {})
40+
41+
// Meta
42+
if (hasMeta(show, episode)) {
43+
store.dispatch(actions.toggleInfo(true))
44+
}
45+
46+
// Audio Modifiers
47+
if (runtime.platform === 'desktop') {
48+
store.dispatch(actions.toggleVolumeSlider(true))
49+
}
50+
51+
// Everything else without conditions
52+
store.dispatch(actions.toggleComponentTab('info', true))
53+
store.dispatch(actions.toggleComponentTab('audio', true))
54+
store.dispatch(actions.toggleInfoPoster(true))
55+
store.dispatch(actions.showPauseButton())
56+
break
57+
case 'ERROR_LOAD':
58+
store.dispatch(actions.toggleInfo(false))
59+
store.dispatch(actions.toggleError(true))
60+
store.dispatch(actions.showRetryButton())
61+
break
62+
case 'ERROR_MISSING_AUDIO_FILES':
63+
store.dispatch(actions.toggleInfo(false))
64+
store.dispatch(actions.toggleError(true))
65+
store.dispatch(actions.toggleButtonControl(false))
66+
break
67+
}
68+
}

0 commit comments

Comments
 (0)