mirror of
https://github.com/badaix/snapcast.git
synced 2025-05-10 07:36:41 +02:00
logging
This commit is contained in:
parent
84cdd5b8ff
commit
e57971c6cb
7 changed files with 671 additions and 52 deletions
100
bug.txt
Normal file
100
bug.txt
Normal file
|
@ -0,0 +1,100 @@
|
|||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 2552778 > 92, chunks: 35, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 2461512 > 92, chunks: 34, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 2369340 > 92, chunks: 33, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 2276977 > 92, chunks: 32, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 2184579 > 92, chunks: 31, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 2092190 > 92, chunks: 30, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 1999795 > 92, chunks: 29, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 1907409 > 92, chunks: 28, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 1816011 > 92, chunks: 27, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 1723643 > 92, chunks: 26, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 1631253 > 92, chunks: 25, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 1538985 > 92, chunks: 24, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 1446600 > 92, chunks: 23, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 1354213 > 92, chunks: 22, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 1266210 > 92, chunks: 22, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 1173955 > 92, chunks: 21, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 1081592 > 92, chunks: 20, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 989316 > 92, chunks: 19, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 896943 > 92, chunks: 18, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 804551 > 92, chunks: 17, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 712152 > 92, chunks: 16, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 619757 > 92, chunks: 15, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 527375 > 92, chunks: 14, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 434978 > 92, chunks: 13, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 342585 > 92, chunks: 12, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 250190 > 92, chunks: 11, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] sleep > chunk_->getDuration(): 157787 > 92, chunks: 10, out: 100000, needed: 25034013
|
||||
2015-02-11 06-53-30 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 06-53-30 [out] Sleep 65289, age: -27457, bufferDuration: 25034
|
||||
2015-02-11 06-53-30 [out] Chunk: -274 -274 -274 -274 1 100000
|
||||
2015-02-11 06-53-40 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 06-53-40 [out] Sleep 65189, age: 9939282, bufferDuration: 25034
|
||||
2015-02-11 06-53-40 [out] Chunk: 99392 99392 99392 99392 1 100000
|
||||
2015-02-11 06-53-50 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 06-53-50 [out] Sleep 65089, age: 19914052, bufferDuration: 25034
|
||||
2015-02-11 06-53-50 [out] Chunk: 199140 199140 199140 199140 1 100000
|
||||
2015-02-11 06-54-00 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 06-54-00 [out] Sleep 64989, age: 29888939, bufferDuration: 25034
|
||||
2015-02-11 06-54-00 [out] Chunk: 298889 298889 298889 298889 1 100000
|
||||
2015-02-11 06-54-10 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 06-54-10 [out] Sleep 64889, age: 19245105, bufferDuration: 25034
|
||||
2015-02-11 06-54-10 [out] Chunk: 192451 192451 192451 192451 1 100000
|
||||
2015-02-11 06-54-20 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 06-54-20 [out] Sleep 64789, age: 29219324, bufferDuration: 25034
|
||||
2015-02-11 06-54-20 [out] Chunk: 292193 292193 292193 292193 1 100000
|
||||
2015-02-11 06-54-30 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 06-54-30 [out] Sleep 64689, age: 39194206, bufferDuration: 25034
|
||||
2015-02-11 06-54-30 [out] Chunk: 391942 391942 391942 391942 1 100000
|
||||
...
|
||||
2015-02-11 07-16-00 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 07-16-00 [out] Sleep 51789, age: 29166609, bufferDuration: 25034
|
||||
2015-02-11 07-16-00 [out] Chunk: 291666 291666 291666 291666 1 100000
|
||||
2015-02-11 07-16-10 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 07-16-10 [out] Sleep 51689, age: 39141449, bufferDuration: 25034
|
||||
2015-02-11 07-16-10 [out] Chunk: 391414 391414 391414 391414 1 100000
|
||||
2015-02-11 07-16-20 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 07-16-20 [out] Sleep 51589, age: 19208741, bufferDuration: 25034
|
||||
2015-02-11 07-16-20 [out] Chunk: 192087 192087 192087 192087 1 100000
|
||||
2015-02-11 07-16-30 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 07-16-30 [out] Sleep 51489, age: 29183951, bufferDuration: 25034
|
||||
2015-02-11 07-16-30 [out] Chunk: 291839 291839 291839 291839 1 100000
|
||||
2015-02-11 07-16-40 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 07-16-40 [out] Sleep 51389, age: 39158778, bufferDuration: 25034
|
||||
2015-02-11 07-16-40 [out] Chunk: 391587 391587 391587 391587 1 100000
|
||||
2015-02-11 07-16-50 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 07-16-50 [out] Sleep 51289, age: 49133134, bufferDuration: 25034
|
||||
2015-02-11 07-16-50 [out] Chunk: 491331 491331 491331 491331 1 100000
|
||||
2015-02-11 07-17-00 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 07-17-00 [out] Sleep 51189, age: 19170398, bufferDuration: 25034
|
||||
2015-02-11 07-17-00 [out] Chunk: 191703 191703 191703 191703 1 100000
|
||||
2015-02-11 07-17-10 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 07-17-10 [out] Sleep 51089, age: 29145503, bufferDuration: 25034
|
||||
2015-02-11 07-17-10 [out] Chunk: 291455 291455 291455 291455 1 100000
|
||||
2015-02-11 07-17-20 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 07-17-20 [out] Sleep 50989, age: 39119549, bufferDuration: 25034
|
||||
2015-02-11 07-17-20 [out] Chunk: 391195 391195 391195 391195 1 100000
|
||||
2015-02-11 07-17-30 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 07-17-30 [out] Sleep 50889, age: 49094582, bufferDuration: 25034
|
||||
2015-02-11 07-17-30 [out] Chunk: 490945 490945 490945 490945 1 100000
|
||||
2015-02-11 07-17-40 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 07-17-40 [out] Sleep 50789, age: 19224557, bufferDuration: 25034
|
||||
2015-02-11 07-17-40 [out] Chunk: 192245 192245 192245 192245 1 100000
|
||||
2015-02-11 07-17-50 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 07-17-50 [out] Sleep 50689, age: 29199351, bufferDuration: 25034
|
||||
2015-02-11 07-17-50 [out] Chunk: 291993 291993 291993 291993 1 100000
|
||||
2015-02-11 07-18-00 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 07-18-00 [out] Sleep 50589, age: 39174527, bufferDuration: 25034
|
||||
2015-02-11 07-18-00 [out] Chunk: 391745 391745 391745 391745 1 100000
|
||||
2015-02-11 07-18-10 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 07-18-10 [out] Sleep 50489, age: 19242269, bufferDuration: 25034
|
||||
2015-02-11 07-18-10 [out] Chunk: 192422 192422 192422 192422 1 100000
|
||||
2015-02-11 07-18-20 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 07-18-20 [out] Sleep 50389, age: 29216343, bufferDuration: 25034
|
||||
2015-02-11 07-18-20 [out] Chunk: 292163 292163 292163 292163 1 100000
|
||||
^[[5~2015-02-11 07-18-30 [out] correction: 4, factor: 1.00362
|
||||
2015-02-11 07-18-30 [out] Sleep 50289, age: 39191836, bufferDuration: 25034
|
||||
2015-02-11 07-18-30 [out] Chunk: 391918 391918 391918 391918 1 100000
|
||||
|
||||
|
||||
|
201
client/browseAvahi.cpp
Normal file
201
client/browseAvahi.cpp
Normal file
|
@ -0,0 +1,201 @@
|
|||
/***
|
||||
This file is part of avahi.
|
||||
|
||||
avahi is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation; either version 2.1 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
avahi is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
||||
Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with avahi; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
***/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <avahi-client/client.h>
|
||||
#include <avahi-client/lookup.h>
|
||||
|
||||
#include <avahi-common/simple-watch.h>
|
||||
#include <avahi-common/malloc.h>
|
||||
#include <avahi-common/error.h>
|
||||
|
||||
static AvahiSimplePoll *simple_poll = NULL;
|
||||
|
||||
static void resolve_callback(
|
||||
AvahiServiceResolver *r,
|
||||
AVAHI_GCC_UNUSED AvahiIfIndex interface,
|
||||
AVAHI_GCC_UNUSED AvahiProtocol protocol,
|
||||
AvahiResolverEvent event,
|
||||
const char *name,
|
||||
const char *type,
|
||||
const char *domain,
|
||||
const char *host_name,
|
||||
const AvahiAddress *address,
|
||||
uint16_t port,
|
||||
AvahiStringList *txt,
|
||||
AvahiLookupResultFlags flags,
|
||||
AVAHI_GCC_UNUSED void* userdata) {
|
||||
|
||||
assert(r);
|
||||
|
||||
/* Called whenever a service has been resolved successfully or timed out */
|
||||
|
||||
switch (event) {
|
||||
case AVAHI_RESOLVER_FAILURE:
|
||||
fprintf(stderr, "(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n", name, type, domain, avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r))));
|
||||
break;
|
||||
|
||||
case AVAHI_RESOLVER_FOUND: {
|
||||
char a[AVAHI_ADDRESS_STR_MAX], *t;
|
||||
|
||||
fprintf(stderr, "Service '%s' of type '%s' in domain '%s':\n", name, type, domain);
|
||||
|
||||
avahi_address_snprint(a, sizeof(a), address);
|
||||
t = avahi_string_list_to_string(txt);
|
||||
fprintf(stderr,
|
||||
"\t%s:%u (%s)\n"
|
||||
"\tTXT=%s\n"
|
||||
"\tProto=%i\n"
|
||||
"\tcookie is %u\n"
|
||||
"\tis_local: %i\n"
|
||||
"\tour_own: %i\n"
|
||||
"\twide_area: %i\n"
|
||||
"\tmulticast: %i\n"
|
||||
"\tcached: %i\n",
|
||||
host_name, port, a,
|
||||
t,
|
||||
(int)protocol,
|
||||
avahi_string_list_get_service_cookie(txt),
|
||||
!!(flags & AVAHI_LOOKUP_RESULT_LOCAL),
|
||||
!!(flags & AVAHI_LOOKUP_RESULT_OUR_OWN),
|
||||
!!(flags & AVAHI_LOOKUP_RESULT_WIDE_AREA),
|
||||
!!(flags & AVAHI_LOOKUP_RESULT_MULTICAST),
|
||||
!!(flags & AVAHI_LOOKUP_RESULT_CACHED));
|
||||
|
||||
avahi_free(t);
|
||||
}
|
||||
}
|
||||
|
||||
avahi_service_resolver_free(r);
|
||||
}
|
||||
|
||||
static void browse_callback(
|
||||
AvahiServiceBrowser *b,
|
||||
AvahiIfIndex interface,
|
||||
AvahiProtocol protocol,
|
||||
AvahiBrowserEvent event,
|
||||
const char *name,
|
||||
const char *type,
|
||||
const char *domain,
|
||||
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
|
||||
void* userdata) {
|
||||
|
||||
AvahiClient *c = (AvahiClient*)userdata;
|
||||
assert(b);
|
||||
|
||||
/* Called whenever a new services becomes available on the LAN or is removed from the LAN */
|
||||
|
||||
switch (event) {
|
||||
case AVAHI_BROWSER_FAILURE:
|
||||
|
||||
fprintf(stderr, "(Browser) %s\n", avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b))));
|
||||
avahi_simple_poll_quit(simple_poll);
|
||||
return;
|
||||
|
||||
case AVAHI_BROWSER_NEW:
|
||||
fprintf(stderr, "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
|
||||
|
||||
/* We ignore the returned resolver object. In the callback
|
||||
function we free it. If the server is terminated before
|
||||
the callback function is called the server will free
|
||||
the resolver for us. */
|
||||
|
||||
if (!(avahi_service_resolver_new(c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, (AvahiLookupFlags)0, resolve_callback, c)))
|
||||
fprintf(stderr, "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_client_errno(c)));
|
||||
|
||||
break;
|
||||
|
||||
case AVAHI_BROWSER_REMOVE:
|
||||
fprintf(stderr, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
|
||||
break;
|
||||
|
||||
case AVAHI_BROWSER_ALL_FOR_NOW:
|
||||
case AVAHI_BROWSER_CACHE_EXHAUSTED:
|
||||
fprintf(stderr, "(Browser) %s\n", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) {
|
||||
assert(c);
|
||||
|
||||
/* Called whenever the client or server state changes */
|
||||
|
||||
if (state == AVAHI_CLIENT_FAILURE) {
|
||||
fprintf(stderr, "Server connection failure: %s\n", avahi_strerror(avahi_client_errno(c)));
|
||||
avahi_simple_poll_quit(simple_poll);
|
||||
}
|
||||
}
|
||||
|
||||
int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char*argv[]) {
|
||||
AvahiClient *client = NULL;
|
||||
AvahiServiceBrowser *sb = NULL;
|
||||
int error;
|
||||
int ret = 1;
|
||||
|
||||
/* Allocate main loop object */
|
||||
if (!(simple_poll = avahi_simple_poll_new())) {
|
||||
fprintf(stderr, "Failed to create simple poll object.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Allocate a new client */
|
||||
client = avahi_client_new(avahi_simple_poll_get(simple_poll), (AvahiClientFlags)0, client_callback, NULL, &error);
|
||||
|
||||
/* Check wether creating the client object succeeded */
|
||||
if (!client) {
|
||||
fprintf(stderr, "Failed to create client: %s\n", avahi_strerror(error));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Create the service browser */
|
||||
if (!(sb = avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_snapcast._tcp", NULL, (AvahiLookupFlags)0, browse_callback, client))) {
|
||||
fprintf(stderr, "Failed to create service browser: %s\n", avahi_strerror(avahi_client_errno(client)));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Run the main loop */
|
||||
avahi_simple_poll_loop(simple_poll);
|
||||
|
||||
ret = 0;
|
||||
|
||||
fail:
|
||||
|
||||
/* Cleanup things */
|
||||
if (sb)
|
||||
avahi_service_browser_free(sb);
|
||||
|
||||
if (client)
|
||||
avahi_client_free(client);
|
||||
|
||||
if (simple_poll)
|
||||
avahi_simple_poll_free(simple_poll);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -5,7 +5,8 @@
|
|||
#include "timeProvider.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace chronos;
|
||||
//using namespace chronos;
|
||||
namespace cs = chronos;
|
||||
|
||||
|
||||
Stream::Stream(const msg::SampleFormat& sampleFormat) : format_(sampleFormat), sleep_(0), median_(0), shortMedian_(0), lastUpdate_(0), playedFrames_(0)
|
||||
|
@ -14,7 +15,7 @@ Stream::Stream(const msg::SampleFormat& sampleFormat) : format_(sampleFormat), s
|
|||
shortBuffer_.setSize(100);
|
||||
miniBuffer_.setSize(20);
|
||||
// cardBuffer_.setSize(50);
|
||||
bufferMs_ = msec(500);
|
||||
bufferMs_ = cs::msec(500);
|
||||
|
||||
/*
|
||||
48000 x
|
||||
|
@ -39,7 +40,7 @@ void Stream::setRealSampleRate(double sampleRate)
|
|||
|
||||
void Stream::setBufferLen(size_t bufferLenMs)
|
||||
{
|
||||
bufferMs_ = msec(bufferLenMs);
|
||||
bufferMs_ = cs::msec(bufferLenMs);
|
||||
}
|
||||
|
||||
|
||||
|
@ -53,7 +54,7 @@ void Stream::clearChunks()
|
|||
|
||||
void Stream::addChunk(msg::PcmChunk* chunk)
|
||||
{
|
||||
while (chunks_.size() * chunk->duration<chronos::msec>().count() > 10000)
|
||||
while (chunks_.size() * chunk->duration<cs::msec>().count() > 10000)
|
||||
chunks_.pop();
|
||||
chunks_.push(shared_ptr<msg::PcmChunk>(chunk));
|
||||
// logD << "new chunk: " << chunk_->getDuration() << ", Chunks: " << chunks_.size() << "\n";
|
||||
|
@ -61,11 +62,11 @@ void Stream::addChunk(msg::PcmChunk* chunk)
|
|||
|
||||
|
||||
|
||||
time_point_hrc Stream::getSilentPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer)
|
||||
cs::time_point_hrc Stream::getSilentPlayerChunk(void* outputBuffer, unsigned long framesPerBuffer)
|
||||
{
|
||||
if (!chunk_)
|
||||
chunk_ = chunks_.pop();
|
||||
time_point_hrc tp = chunk_->start();
|
||||
cs::time_point_hrc tp = chunk_->start();
|
||||
memset(outputBuffer, 0, framesPerBuffer * format_.frameSize);
|
||||
return tp;
|
||||
}
|
||||
|
@ -98,10 +99,10 @@ time_point_hrc Stream::seek(long ms)
|
|||
return chunk_->start();
|
||||
|
||||
// time_point_ms tp = chunk_->timePoint();
|
||||
while (ms > chunk_->duration<chronos::msec>().count())
|
||||
while (ms > chunk_->duration<cs::msec>().count())
|
||||
{
|
||||
chunk_ = chunks_.pop();
|
||||
ms -= min(ms, (long)chunk_->durationLeft<chronos::msec>().count());
|
||||
ms -= min(ms, (long)chunk_->durationLeft<cs::msec>().count());
|
||||
}
|
||||
chunk_->seek(ms * format_.msRate());
|
||||
return chunk_->start();
|
||||
|
@ -109,12 +110,12 @@ time_point_hrc Stream::seek(long ms)
|
|||
*/
|
||||
|
||||
|
||||
time_point_hrc Stream::getNextPlayerChunk(void* outputBuffer, const chronos::usec& timeout, unsigned long framesPerBuffer)
|
||||
cs::time_point_hrc Stream::getNextPlayerChunk(void* outputBuffer, const cs::usec& timeout, unsigned long framesPerBuffer)
|
||||
{
|
||||
if (!chunk_ && !chunks_.try_pop(chunk_, timeout))
|
||||
throw 0;
|
||||
|
||||
time_point_hrc tp = chunk_->start();
|
||||
cs::time_point_hrc tp = chunk_->start();
|
||||
char* buffer = (char*)outputBuffer;
|
||||
unsigned long read = 0;
|
||||
while (read < framesPerBuffer)
|
||||
|
@ -127,14 +128,14 @@ time_point_hrc Stream::getNextPlayerChunk(void* outputBuffer, const chronos::use
|
|||
}
|
||||
|
||||
|
||||
time_point_hrc Stream::getNextPlayerChunk(void* outputBuffer, const chronos::usec& timeout, unsigned long framesPerBuffer, long framesCorrection)
|
||||
cs::time_point_hrc Stream::getNextPlayerChunk(void* outputBuffer, const cs::usec& timeout, unsigned long framesPerBuffer, long framesCorrection)
|
||||
{
|
||||
if (framesCorrection == 0)
|
||||
return getNextPlayerChunk(outputBuffer, timeout, framesPerBuffer);
|
||||
|
||||
long toRead = framesPerBuffer + framesCorrection;
|
||||
char* buffer = (char*)malloc(toRead * format_.frameSize);
|
||||
time_point_hrc tp = getNextPlayerChunk(buffer, timeout, toRead);
|
||||
cs::time_point_hrc tp = getNextPlayerChunk(buffer, timeout, toRead);
|
||||
|
||||
float factor = (float)toRead / framesPerBuffer;//(float)(framesPerBuffer*channels_);
|
||||
if (abs(framesCorrection) > 1)
|
||||
|
@ -170,28 +171,33 @@ void Stream::resetBuffers()
|
|||
|
||||
|
||||
|
||||
bool Stream::getPlayerChunk(void* outputBuffer, const chronos::usec& outputBufferDacTime, unsigned long framesPerBuffer)
|
||||
bool Stream::getPlayerChunk(void* outputBuffer, const cs::usec& outputBufferDacTime, unsigned long framesPerBuffer)
|
||||
{
|
||||
if (outputBufferDacTime > bufferMs_)
|
||||
{
|
||||
logO << "outputBufferDacTime > bufferMs: " << outputBufferDacTime.count() << " > " << std::chrono::duration_cast<usec>(bufferMs_).count() << "\n";
|
||||
sleep_ = chronos::usec(0);
|
||||
logO << "outputBufferDacTime > bufferMs: " << cs::duration<cs::msec>(outputBufferDacTime) << " > " << cs::duration<cs::msec>(bufferMs_) << "\n";
|
||||
sleep_ = cs::usec(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!chunk_ && !chunks_.try_pop(chunk_, outputBufferDacTime))
|
||||
{
|
||||
logO << "!chunk_ && !chunks_.try_pop(chunk_, outputBufferDacTime)\n";
|
||||
sleep_ = chronos::usec(0);
|
||||
logO << "no chunks available\n";
|
||||
sleep_ = cs::usec(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
playedFrames_ += framesPerBuffer;
|
||||
|
||||
chronos::usec age = std::chrono::duration_cast<usec>(TimeProvider::serverNow() - chunk_->start() - bufferMs_ + outputBufferDacTime);
|
||||
if ((sleep_.count() == 0) && (chronos::abs(age) > chronos::msec(200)))
|
||||
/// we have a chunk
|
||||
/// age = chunk age (server now - rec time: some positive value) - buffer (e.g. 1000ms) + time to DAC
|
||||
/// age = 0 => play now
|
||||
/// age < 0 => play in -age
|
||||
/// age > 0 => too old
|
||||
cs::usec age = std::chrono::duration_cast<cs::usec>(TimeProvider::serverNow() - chunk_->start() - bufferMs_ + outputBufferDacTime);
|
||||
if ((sleep_.count() == 0) && (cs::abs(age) > cs::msec(200)))
|
||||
{
|
||||
logO << "age > 200: " << age.count() << "\n";
|
||||
logO << "age > 200: " << cs::duration<cs::msec>(age) << "\n";
|
||||
sleep_ = age;
|
||||
}
|
||||
|
||||
|
@ -199,54 +205,56 @@ bool Stream::getPlayerChunk(void* outputBuffer, const chronos::usec& outputBuffe
|
|||
{
|
||||
|
||||
//logD << "framesPerBuffer: " << framesPerBuffer << "\tms: " << framesPerBuffer*2 / PLAYER_CHUNK_MS_SIZE << "\t" << PLAYER_CHUNK_SIZE << "\n";
|
||||
chronos::nsec bufferDuration = chronos::nsec(chronos::usec::rep(framesPerBuffer / format_.nsRate()));
|
||||
cs::nsec bufferDuration = cs::nsec(cs::nsec::rep(framesPerBuffer / format_.nsRate()));
|
||||
// logD << "buffer duration: " << bufferDuration.count() << "\n";
|
||||
|
||||
chronos::usec correction = chronos::usec(0);
|
||||
cs::usec correction = cs::usec(0);
|
||||
if (sleep_.count() != 0)
|
||||
{
|
||||
resetBuffers();
|
||||
if (sleep_ < -bufferDuration/2)
|
||||
{
|
||||
logO << "sleep < -bufferDuration/2: " << cs::duration<cs::msec>(sleep_) << " < " << -cs::duration<cs::msec>(bufferDuration)/2 << ", ";
|
||||
// We're early: not enough chunks_. play silence. Reference chunk_ is the oldest (front) one
|
||||
sleep_ = chrono::duration_cast<usec>(TimeProvider::serverNow() - getSilentPlayerChunk(outputBuffer, framesPerBuffer) - bufferMs_ + outputBufferDacTime);
|
||||
//logD << "-sleep: " << sleep_.count() << " " << -bufferDuration.count() / 2000 << "\n";
|
||||
sleep_ = chrono::duration_cast<cs::usec>(TimeProvider::serverNow() - getSilentPlayerChunk(outputBuffer, framesPerBuffer) - bufferMs_ + outputBufferDacTime);
|
||||
logO << "sleep: " << cs::duration<cs::msec>(sleep_) << "\n";
|
||||
if (sleep_ < -bufferDuration/2)
|
||||
return true;
|
||||
}
|
||||
else if (sleep_ > bufferDuration/2)
|
||||
{
|
||||
logO << "sleep > bufferDuration/2: " << cs::duration<cs::msec>(sleep_) << " > " << cs::duration<cs::msec>(bufferDuration)/2 << "\n";
|
||||
// We're late: discard oldest chunks
|
||||
while (sleep_ > chunk_->duration<chronos::usec>())
|
||||
while (sleep_ > chunk_->duration<cs::usec>())
|
||||
{
|
||||
logO << "sleep > chunk_->getDuration(): " << sleep_.count() << " > " << chunk_->duration<chronos::msec>().count() << ", chunks: " << chunks_.size() << ", out: " << outputBufferDacTime.count() << ", needed: " << bufferDuration.count() << "\n";
|
||||
sleep_ = std::chrono::duration_cast<usec>(TimeProvider::serverNow() - chunk_->start() - bufferMs_ + outputBufferDacTime);
|
||||
logO << "sleep > chunkDuration: " << cs::duration<cs::msec>(sleep_) << " > " << chunk_->duration<cs::msec>().count() << ", chunks: " << chunks_.size() << ", out: " << cs::duration<cs::msec>(outputBufferDacTime) << ", needed: " << cs::duration<cs::msec>(bufferDuration) << "\n";
|
||||
sleep_ = std::chrono::duration_cast<cs::usec>(TimeProvider::serverNow() - chunk_->start() - bufferMs_ + outputBufferDacTime);
|
||||
if (!chunks_.try_pop(chunk_, outputBufferDacTime))
|
||||
{
|
||||
logO << "no chunks available\n";
|
||||
chunk_ = NULL;
|
||||
sleep_ = chronos::usec(0);
|
||||
sleep_ = cs::usec(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// out of sync, can be corrected by playing faster/slower
|
||||
if (sleep_ < -chronos::usec(100))
|
||||
if (sleep_ < -cs::usec(100))
|
||||
{
|
||||
sleep_ += chronos::usec(100);
|
||||
correction = -chronos::usec(100);
|
||||
sleep_ += cs::usec(100);
|
||||
correction = -cs::usec(100);
|
||||
}
|
||||
else if (sleep_ > chronos::usec(100))
|
||||
else if (sleep_ > cs::usec(100))
|
||||
{
|
||||
sleep_ -= chronos::usec(100);
|
||||
correction = chronos::usec(100);
|
||||
sleep_ -= cs::usec(100);
|
||||
correction = cs::usec(100);
|
||||
}
|
||||
else
|
||||
{
|
||||
logO << "Sleep " << sleep_.count() << "\n";
|
||||
logO << "Sleep " << cs::duration<cs::msec>(sleep_) << "\n";
|
||||
correction = sleep_;
|
||||
sleep_ = chronos::usec(0);
|
||||
sleep_ = cs::usec(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -257,55 +265,55 @@ bool Stream::getPlayerChunk(void* outputBuffer, const chronos::usec& outputBuffe
|
|||
playedFrames_ -= abs(correctAfterXFrames_);
|
||||
}
|
||||
|
||||
age = std::chrono::duration_cast<usec>(TimeProvider::serverNow() - getNextPlayerChunk(outputBuffer, outputBufferDacTime, framesPerBuffer, framesCorrection) - bufferMs_ + outputBufferDacTime);
|
||||
age = std::chrono::duration_cast<cs::usec>(TimeProvider::serverNow() - getNextPlayerChunk(outputBuffer, outputBufferDacTime, framesPerBuffer, framesCorrection) - bufferMs_ + outputBufferDacTime);
|
||||
|
||||
setRealSampleRate(format_.rate);
|
||||
if (sleep_.count() == 0)
|
||||
{
|
||||
if (buffer_.full())
|
||||
{
|
||||
if (chronos::usec(abs(median_)) > chronos::msec(1))
|
||||
if (cs::usec(abs(median_)) > cs::msec(1))
|
||||
{
|
||||
logO << "pBuffer->full() && (abs(median_) > 1): " << median_ << "\n";
|
||||
sleep_ = chronos::usec(shortMedian_);
|
||||
sleep_ = cs::usec(shortMedian_);
|
||||
}
|
||||
/* else if (chronos::usec(median_) > chronos::usec(300))
|
||||
/* else if (cs::usec(median_) > cs::usec(300))
|
||||
{
|
||||
setRealSampleRate(format_.rate - format_.rate / 1000);
|
||||
}
|
||||
else if (chronos::usec(median_) < -chronos::usec(300))
|
||||
else if (cs::usec(median_) < -cs::usec(300))
|
||||
{
|
||||
setRealSampleRate(format_.rate + format_.rate / 1000);
|
||||
}
|
||||
*/ }
|
||||
else if (shortBuffer_.full())
|
||||
{
|
||||
if (chronos::usec(abs(shortMedian_)) > chronos::msec(5))
|
||||
if (cs::usec(abs(shortMedian_)) > cs::msec(5))
|
||||
{
|
||||
logO << "pShortBuffer->full() && (abs(shortMedian_) > 5): " << shortMedian_ << "\n";
|
||||
sleep_ = chronos::usec(shortMedian_);
|
||||
sleep_ = cs::usec(shortMedian_);
|
||||
}
|
||||
/* else
|
||||
{
|
||||
setRealSampleRate(format_.rate + -shortMedian_ / 100);
|
||||
}
|
||||
*/ }
|
||||
else if (miniBuffer_.full() && (chronos::usec(abs(miniBuffer_.median())) > chronos::msec(50)))
|
||||
else if (miniBuffer_.full() && (cs::usec(abs(miniBuffer_.median())) > cs::msec(50)))
|
||||
{
|
||||
logO << "pMiniBuffer->full() && (abs(pMiniBuffer->mean()) > 50): " << miniBuffer_.median() << "\n";
|
||||
sleep_ = chronos::usec((chronos::msec::rep)miniBuffer_.mean());
|
||||
sleep_ = cs::usec((cs::msec::rep)miniBuffer_.mean());
|
||||
}
|
||||
}
|
||||
|
||||
if (sleep_.count() != 0)
|
||||
{
|
||||
logO << "Sleep " << sleep_.count() << ", age: " << age.count() << ", bufferDuration: " << std::chrono::duration_cast<usec>(bufferDuration).count() << "\n";
|
||||
logO << "Sleep " << cs::duration<cs::msec>(sleep_) << ", age: " << cs::duration<cs::msec>(age) << ", bufferDuration: " << cs::duration<cs::msec>(bufferDuration) << "\n";
|
||||
}
|
||||
else if (shortBuffer_.full())
|
||||
{
|
||||
if (chronos::usec(shortMedian_) > chronos::usec(100))
|
||||
if (cs::usec(shortMedian_) > cs::usec(100))
|
||||
setRealSampleRate(format_.rate * 0.9999);
|
||||
else if (chronos::usec(shortMedian_) < -chronos::usec(100))
|
||||
else if (cs::usec(shortMedian_) < -cs::usec(100))
|
||||
setRealSampleRate(format_.rate * 1.0001);
|
||||
}
|
||||
|
||||
|
@ -318,13 +326,13 @@ bool Stream::getPlayerChunk(void* outputBuffer, const chronos::usec& outputBuffe
|
|||
lastUpdate_ = now;
|
||||
median_ = buffer_.median();
|
||||
shortMedian_ = shortBuffer_.median();
|
||||
logO << "Chunk: " << age.count()/100 << "\t" << miniBuffer_.median()/100 << "\t" << shortMedian_/100 << "\t" << median_/100 << "\t" << buffer_.size() << "\t" << outputBufferDacTime.count() << "\n";
|
||||
logO << "Chunk: " << age.count()/100 << "\t" << miniBuffer_.median()/100 << "\t" << shortMedian_/100 << "\t" << median_/100 << "\t" << buffer_.size() << "\t" << cs::duration<cs::msec>(outputBufferDacTime) << "\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch(int e)
|
||||
{
|
||||
sleep_ = chronos::usec(0);
|
||||
sleep_ = cs::usec(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,12 @@ namespace chronos
|
|||
Rep x = d.count();
|
||||
return std::chrono::duration<Rep, Period>(x >= 0 ? x : -x);
|
||||
}
|
||||
|
||||
template <class ToDuration, class Rep, class Period>
|
||||
int64_t duration(std::chrono::duration<Rep, Period> d)
|
||||
{
|
||||
return std::chrono::duration_cast<ToDuration>(d).count();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
271
server/publishAvahi.cpp
Normal file
271
server/publishAvahi.cpp
Normal file
|
@ -0,0 +1,271 @@
|
|||
/***
|
||||
This file is part of avahi.
|
||||
|
||||
avahi is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation; either version 2.1 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
avahi is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
||||
Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with avahi; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
***/
|
||||
|
||||
#include "publishAvahi.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <avahi-client/client.h>
|
||||
#include <avahi-client/publish.h>
|
||||
|
||||
#include <avahi-common/alternative.h>
|
||||
#include <avahi-common/simple-watch.h>
|
||||
#include <avahi-common/malloc.h>
|
||||
#include <avahi-common/error.h>
|
||||
#include <avahi-common/timeval.h>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
|
||||
PublishAvahi::PublishAvahi() : group(NULL), simple_poll(NULL), name(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PublishAvahi::~PublishAvahi()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void PublishAvahi::entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, AVAHI_GCC_UNUSED void *userdata) {
|
||||
assert(g == group || group == NULL);
|
||||
group = g;
|
||||
|
||||
/* Called whenever the entry group state changes */
|
||||
|
||||
switch (state) {
|
||||
case AVAHI_ENTRY_GROUP_ESTABLISHED :
|
||||
/* The entry group has been established successfully */
|
||||
fprintf(stderr, "Service '%s' successfully established.\n", name);
|
||||
break;
|
||||
|
||||
case AVAHI_ENTRY_GROUP_COLLISION : {
|
||||
char *n;
|
||||
|
||||
/* A service name collision with a remote service
|
||||
* happened. Let's pick a new name */
|
||||
n = avahi_alternative_service_name(name);
|
||||
avahi_free(name);
|
||||
name = n;
|
||||
|
||||
fprintf(stderr, "Service name collision, renaming service to '%s'\n", name);
|
||||
|
||||
/* And recreate the services */
|
||||
create_services(avahi_entry_group_get_client(g));
|
||||
break;
|
||||
}
|
||||
|
||||
case AVAHI_ENTRY_GROUP_FAILURE :
|
||||
|
||||
fprintf(stderr, "Entry group failure: %s\n", avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))));
|
||||
|
||||
/* Some kind of failure happened while we were registering our services */
|
||||
avahi_simple_poll_quit(simple_poll);
|
||||
break;
|
||||
|
||||
case AVAHI_ENTRY_GROUP_UNCOMMITED:
|
||||
case AVAHI_ENTRY_GROUP_REGISTERING:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void PublishAvahi::create_services(AvahiClient *c) {
|
||||
char *n, r[128];
|
||||
int ret;
|
||||
assert(c);
|
||||
|
||||
/* If this is the first time we're called, let's create a new
|
||||
* entry group if necessary */
|
||||
|
||||
if (!group)
|
||||
{
|
||||
if (!(group = avahi_entry_group_new(c, (void(*)(AvahiEntryGroup*, AvahiEntryGroupState, void*))std::bind(&PublishAvahi::entry_group_callback, this), NULL))) {
|
||||
fprintf(stderr, "avahi_entry_group_new() failed: %s\n", avahi_strerror(avahi_client_errno(c)));
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
/* If the group is empty (either because it was just created, or
|
||||
* because it was reset previously, add our entries. */
|
||||
|
||||
if (avahi_entry_group_is_empty(group)) {
|
||||
fprintf(stderr, "Adding service '%s'\n", name);
|
||||
|
||||
/* Create some random TXT data */
|
||||
snprintf(r, sizeof(r), "random=%i", rand());
|
||||
|
||||
/* We will now add two services and one subtype to the entry
|
||||
* group. The two services have the same name, but differ in
|
||||
* the service type (IPP vs. BSD LPR). Only services with the
|
||||
* same name should be put in the same entry group. */
|
||||
|
||||
/* Add the service for IPP */
|
||||
/* if ((ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AVAHI_PUBLISH_UNIQUE, name, "_ipp._tcp", NULL, NULL, 651, "test=blah", r, NULL)) < 0) {
|
||||
|
||||
if (ret == AVAHI_ERR_COLLISION)
|
||||
goto collision;
|
||||
|
||||
fprintf(stderr, "Failed to add _ipp._tcp service: %s\n", avahi_strerror(ret));
|
||||
goto fail;
|
||||
}
|
||||
*/
|
||||
/* Add the same service for BSD LPR */
|
||||
if ((ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AvahiPublishFlags(0), name, "_snapcast._tcp", NULL, NULL, 515, NULL)) < 0) {
|
||||
|
||||
if (ret == AVAHI_ERR_COLLISION)
|
||||
goto collision;
|
||||
|
||||
fprintf(stderr, "Failed to add _snapcast._tcp service: %s\n", avahi_strerror(ret));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Add an additional (hypothetic) subtype */
|
||||
/* if ((ret = avahi_entry_group_add_service_subtype(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AvahiPublishFlags(0), name, "_printer._tcp", NULL, "_magic._sub._printer._tcp") < 0)) {
|
||||
fprintf(stderr, "Failed to add subtype _magic._sub._printer._tcp: %s\n", avahi_strerror(ret));
|
||||
goto fail;
|
||||
}
|
||||
*/
|
||||
/* Tell the server to register the service */
|
||||
if ((ret = avahi_entry_group_commit(group)) < 0) {
|
||||
fprintf(stderr, "Failed to commit entry group: %s\n", avahi_strerror(ret));
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
collision:
|
||||
|
||||
/* A service name collision with a local service happened. Let's
|
||||
* pick a new name */
|
||||
n = avahi_alternative_service_name(name);
|
||||
avahi_free(name);
|
||||
name = n;
|
||||
|
||||
fprintf(stderr, "Service name collision, renaming service to '%s'\n", name);
|
||||
|
||||
avahi_entry_group_reset(group);
|
||||
|
||||
create_services(c);
|
||||
return;
|
||||
|
||||
fail:
|
||||
avahi_simple_poll_quit(simple_poll);
|
||||
}
|
||||
|
||||
void PublishAvahi::client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) {
|
||||
assert(c);
|
||||
|
||||
/* Called whenever the client or server state changes */
|
||||
|
||||
switch (state) {
|
||||
case AVAHI_CLIENT_S_RUNNING:
|
||||
|
||||
/* The server has startup successfully and registered its host
|
||||
* name on the network, so it's time to create our services */
|
||||
create_services(c);
|
||||
break;
|
||||
|
||||
case AVAHI_CLIENT_FAILURE:
|
||||
|
||||
fprintf(stderr, "Client failure: %s\n", avahi_strerror(avahi_client_errno(c)));
|
||||
avahi_simple_poll_quit(simple_poll);
|
||||
|
||||
break;
|
||||
|
||||
case AVAHI_CLIENT_S_COLLISION:
|
||||
|
||||
/* Let's drop our registered services. When the server is back
|
||||
* in AVAHI_SERVER_RUNNING state we will register them
|
||||
* again with the new host name. */
|
||||
|
||||
case AVAHI_CLIENT_S_REGISTERING:
|
||||
|
||||
/* The server records are now being established. This
|
||||
* might be caused by a host name change. We need to wait
|
||||
* for our own records to register until the host name is
|
||||
* properly esatblished. */
|
||||
|
||||
if (group)
|
||||
avahi_entry_group_reset(group);
|
||||
|
||||
break;
|
||||
|
||||
case AVAHI_CLIENT_CONNECTING:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char*argv[]) {
|
||||
PublishAvahi publishAvahi;
|
||||
|
||||
AvahiClient *client = NULL;
|
||||
int error;
|
||||
int ret = 1;
|
||||
struct timeval tv;
|
||||
|
||||
/* Allocate main loop object */
|
||||
if (!(simple_poll = avahi_simple_poll_new())) {
|
||||
fprintf(stderr, "Failed to create simple poll object.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
name = avahi_strdup("MegaPrinter");
|
||||
|
||||
/* Allocate a new client */
|
||||
client = avahi_client_new(avahi_simple_poll_get(simple_poll), AVAHI_CLIENT_IGNORE_USER_CONFIG, client_callback, NULL, &error);
|
||||
|
||||
/* Check wether creating the client object succeeded */
|
||||
if (!client) {
|
||||
fprintf(stderr, "Failed to create client: %s\n", avahi_strerror(error));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* After 10s do some weird modification to the service */
|
||||
/* avahi_simple_poll_get(simple_poll)->timeout_new(
|
||||
avahi_simple_poll_get(simple_poll),
|
||||
avahi_elapse_time(&tv, 1000*10, 0),
|
||||
modify_callback,
|
||||
client);
|
||||
*/
|
||||
/* Run the main loop */
|
||||
while (avahi_simple_poll_iterate(simple_poll, 100) == 0)
|
||||
printf("1");
|
||||
|
||||
ret = 0;
|
||||
|
||||
fail:
|
||||
|
||||
/* Cleanup things */
|
||||
|
||||
if (client)
|
||||
avahi_client_free(client);
|
||||
|
||||
if (simple_poll)
|
||||
avahi_simple_poll_free(simple_poll);
|
||||
|
||||
avahi_free(name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
33
server/publishAvahi.h
Normal file
33
server/publishAvahi.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
#ifndef PUBLISH_AVAHI_H
|
||||
#define PUBLISH_AVAHI_H
|
||||
|
||||
#include <avahi-client/client.h>
|
||||
#include <avahi-client/publish.h>
|
||||
|
||||
#include <avahi-common/alternative.h>
|
||||
#include <avahi-common/simple-watch.h>
|
||||
#include <avahi-common/malloc.h>
|
||||
#include <avahi-common/error.h>
|
||||
#include <avahi-common/timeval.h>
|
||||
#include <string>
|
||||
|
||||
class PublishAvahi
|
||||
{
|
||||
public:
|
||||
PublishAvahi();
|
||||
~PublishAvahi();
|
||||
|
||||
private:
|
||||
void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, AVAHI_GCC_UNUSED void *userdata);
|
||||
void create_services(AvahiClient *c);
|
||||
void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata);
|
||||
|
||||
AvahiEntryGroup *group;
|
||||
AvahiSimplePoll *simple_poll;
|
||||
char* name;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -118,10 +118,10 @@ int main(int argc, char* argv[])
|
|||
int fd = open(fifoName.c_str(), O_RDONLY | O_NONBLOCK);
|
||||
try
|
||||
{
|
||||
shared_ptr<msg::PcmChunk> chunk;//(new WireChunk());
|
||||
shared_ptr<msg::PcmChunk> chunk;
|
||||
while (!g_terminated)//cin.good())
|
||||
{
|
||||
chunk.reset(new msg::PcmChunk(sampleFormat, duration));//2*WIRE_CHUNK_SIZE));
|
||||
chunk.reset(new msg::PcmChunk(sampleFormat, duration));
|
||||
int toRead = chunk->payloadSize;
|
||||
int len = 0;
|
||||
do
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue