-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #30 from jmillerv/4-podcast-support
4 podcast support
- Loading branch information
Showing
10 changed files
with
257 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,114 @@ | ||
package content | ||
|
||
import log "github.com/sirupsen/logrus" | ||
import ( | ||
"github.com/mmcdole/gofeed" | ||
"github.com/pkg/errors" | ||
log "github.com/sirupsen/logrus" | ||
"os/exec" | ||
) | ||
|
||
const ( | ||
playOrderNewest PlayOrder = "newest" | ||
playOrderOldest PlayOrder = "oldest" | ||
playOrderRandom PlayOrder = "random" | ||
) | ||
|
||
var pods podcasts // holds the feed data for podcasts | ||
var podcastStream streamPlayer | ||
|
||
type Podcast struct { | ||
Name string | ||
URL string | ||
Path string | ||
Content []byte | ||
Name string | ||
URL string | ||
Player streamPlayer | ||
PlayOrder PlayOrder // options: newest, oldest, random | ||
} | ||
|
||
type PlayOrder string | ||
|
||
// Get parses a podcast feed and sets the most recent episode as the Podcast content. | ||
func (p *Podcast) Get() error { | ||
panic("implement me") | ||
var ep episode | ||
parser := gofeed.NewParser() | ||
feed, err := parser.ParseURL(p.URL) | ||
if err != nil { | ||
return err | ||
} | ||
// traverse links | ||
for _, item := range feed.Items { | ||
pods.Episodes = append(pods.Episodes, item) | ||
} | ||
|
||
switch p.PlayOrder { | ||
case playOrderNewest: | ||
ep = pods.getNewestEpisode() | ||
break | ||
case playOrderOldest: | ||
log.Panic("implement me") | ||
//ep = pods.getOldestEpisode() | ||
case playOrderRandom: | ||
log.Panic("implement me") | ||
//ep = pods.getRandomEpisode() | ||
} | ||
|
||
// setup podcast stream | ||
log.Infof("extension: %v", ep.EpExtension) | ||
podcastStream.playerName = streamPlayerName | ||
podcastStream.url = ep.EpURL | ||
podcastStream.command = exec.Command(podcastStream.playerName, "-quiet", podcastStream.url) | ||
podcastStream.in, err = podcastStream.command.StdinPipe() | ||
if err != nil { | ||
return errors.Wrap(err, "error creating standard pipe in") | ||
} | ||
podcastStream.out, err = podcastStream.command.StdoutPipe() | ||
if err != nil { | ||
return errors.Wrap(err, "error creating standard pipe out") | ||
} | ||
|
||
podcastStream.isPlaying = false | ||
|
||
p.Player = podcastStream | ||
|
||
return nil | ||
} | ||
|
||
// Play sends the audio to the output. It caches a played episode in the cache ofr later checks. | ||
func (p *Podcast) Play() error { | ||
panic("implement me") | ||
log.Infof("streaming from %v ", p.URL) | ||
if !p.Player.isPlaying { | ||
err := p.Player.command.Start() | ||
if err != nil { | ||
return errors.Wrap(err, "error starting podcast streamPlayer") | ||
} | ||
p.Player.isPlaying = true | ||
done := make(chan bool) | ||
func() { | ||
p.Player.pipeChan <- p.Player.out | ||
done <- true | ||
}() | ||
<-done | ||
} | ||
return nil | ||
} | ||
|
||
func (p *Podcast) Stop() error { | ||
log.Infof("Stopping stream from %v ", p.Path) | ||
log.Infof("Stopping stream from %v ", p.URL) | ||
if p.Player.isPlaying { | ||
p.Player.isPlaying = false | ||
_, err := p.Player.in.Write([]byte("q")) | ||
if err != nil { | ||
log.WithError(err).Error("error stopping web radio streamPlayerName: w.Player.in.Write()") | ||
} | ||
err = p.Player.in.Close() | ||
if err != nil { | ||
log.WithError(err).Error("error stopping web radio streamPlayerName: w.Player.in.Close()") | ||
} | ||
err = p.Player.out.Close() | ||
if err != nil { | ||
log.WithError(err).Error("error stopping web radio streamPlayerName: w.Player.out.Close()") | ||
} | ||
p.Player.command = nil | ||
|
||
p.Player.url = "" | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package content | ||
|
||
import ( | ||
"github.com/mmcdole/gofeed" | ||
"math/rand" | ||
"time" | ||
) | ||
|
||
type podcasts struct { | ||
Episodes []*gofeed.Item | ||
// add podcast cache | ||
} | ||
|
||
func (p *podcasts) getNewestEpisode() episode { | ||
var newestEpisode episode | ||
var date *time.Time | ||
date = p.Episodes[0].PublishedParsed | ||
for _, ep := range p.Episodes { | ||
// TODO if played, log that it's in the cache, and skip to the next episode | ||
if ep.PublishedParsed.After(*date) || ep.PublishedParsed.Equal(*date) { | ||
date = ep.PublishedParsed | ||
newestEpisode.Item = ep | ||
newestEpisode.EpURL = ep.Enclosures[0].URL | ||
newestEpisode.EpExtension = ep.Enclosures[0].Type | ||
} | ||
} | ||
return newestEpisode | ||
} | ||
|
||
func (p *podcasts) getOldestEpisode() *episode { | ||
var oldestEpisode *episode | ||
var date *time.Time | ||
// TODO if played, log that it's in the cache, and skip to the next episode | ||
for _, ep := range p.Episodes { | ||
date = p.Episodes[0].PublishedParsed | ||
if ep.PublishedParsed.Before(*date) || ep.PublishedParsed.Equal(*date) { | ||
date = ep.PublishedParsed | ||
oldestEpisode.Item = ep | ||
oldestEpisode.EpURL = ep.Enclosures[0].URL | ||
oldestEpisode.EpExtension = ep.Enclosures[0].Type | ||
} | ||
} | ||
return oldestEpisode | ||
} | ||
|
||
func (p *podcasts) getRandomEpisode() *episode { | ||
var randomEpisode *episode | ||
rand.Seed(time.Now().UnixNano()) | ||
item := p.Episodes[rand.Intn(len(p.Episodes))] | ||
// TODO if played, log that it's in the cache, and skip to the next episode | ||
randomEpisode.Item = item | ||
randomEpisode.EpExtension = item.Enclosures[0].Type | ||
randomEpisode.EpURL = item.Enclosures[0].URL | ||
return randomEpisode | ||
} | ||
|
||
func (p *podcasts) checkIfPlayed(guid string) bool { | ||
return false | ||
} | ||
|
||
type episode struct { | ||
Item *gofeed.Item // Keep this to hold the additional data | ||
EpExtension string | ||
EpURL string | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package content | ||
|
||
import ( | ||
"io" | ||
"os/exec" | ||
) | ||
|
||
type streamPlayer struct { | ||
playerName string | ||
url string | ||
isPlaying bool | ||
command *exec.Cmd | ||
in io.WriteCloser | ||
out io.ReadCloser | ||
pipeChan chan io.ReadCloser | ||
} |
Oops, something went wrong.