static inline bool can_reconnect(const obs_output_t *output, int code) { bool reconnect_active = output->reconnect_retry_max != 0; return (reconnecting(output) && code != OBS_OUTPUT_SUCCESS) || (reconnect_active && code == OBS_OUTPUT_DISCONNECTED); }
static void output_reconnect(struct obs_output *output) { int ret; if (!reconnecting(output)) { output->reconnect_retry_cur_sec = output->reconnect_retry_sec; output->reconnect_retries = 0; } if (output->reconnect_retries >= output->reconnect_retry_max) { output->stop_code = OBS_OUTPUT_DISCONNECTED; os_atomic_set_bool(&output->reconnecting, false); if (delay_active(output)) os_atomic_set_bool(&output->delay_active, false); obs_output_end_data_capture(output); return; } if (!reconnecting(output)) { os_atomic_set_bool(&output->reconnecting, true); os_event_reset(output->reconnect_stop_event); } if (output->reconnect_retries) { output->reconnect_retry_cur_sec *= 2; if (output->reconnect_retry_cur_sec > MAX_RETRY_SEC) output->reconnect_retry_cur_sec = MAX_RETRY_SEC; } output->reconnect_retries++; output->stop_code = OBS_OUTPUT_DISCONNECTED; ret = pthread_create(&output->reconnect_thread, NULL, &reconnect_thread, output); if (ret < 0) { blog(LOG_WARNING, "Failed to create reconnect thread"); os_atomic_set_bool(&output->reconnecting, false); } else { blog(LOG_INFO, "Output '%s': Reconnecting in %d seconds..", output->context.name, output->reconnect_retry_sec); signal_reconnect(output); } }
void obs_output_actual_stop(obs_output_t *output, bool force, uint64_t ts) { bool call_stop = true; bool was_reconnecting = false; if (stopping(output)) return; os_event_reset(output->stopping_event); was_reconnecting = reconnecting(output) && !delay_active(output); if (reconnecting(output)) { os_event_signal(output->reconnect_stop_event); if (output->reconnect_thread_active) pthread_join(output->reconnect_thread, NULL); } if (force) { if (delay_active(output)) { call_stop = delay_capturing(output); os_atomic_set_bool(&output->delay_active, false); os_atomic_set_bool(&output->delay_capturing, false); output->stop_code = OBS_OUTPUT_SUCCESS; obs_output_end_data_capture(output); os_event_signal(output->stopping_event); } else { call_stop = data_active(output); } } else { call_stop = data_active(output); } if (output->context.data && call_stop) { output->info.stop(output->context.data, ts); } else if (was_reconnecting) { output->stop_code = OBS_OUTPUT_SUCCESS; signal_stop(output); os_event_signal(output->stopping_event); } }
void obs_output_stop(obs_output_t *output) { bool encoded; if (!obs_output_valid(output, "obs_output_stop")) return; if (!output->context.data) return; if (!active(output) && !reconnecting(output)) return; if (reconnecting(output)) { obs_output_force_stop(output); return; } encoded = (output->info.flags & OBS_OUTPUT_ENCODED) != 0; if (encoded && output->active_delay_ns) { obs_output_delay_stop(output); } else if (!stopping(output)) { do_output_signal(output, "stopping"); obs_output_actual_stop(output, false, os_gettime_ns()); } }
static bool begin_delayed_capture(obs_output_t *output) { if (delay_capturing(output)) return false; pthread_mutex_lock(&output->interleaved_mutex); reset_packet_data(output); os_atomic_set_bool(&output->delay_capturing, true); pthread_mutex_unlock(&output->interleaved_mutex); if (reconnecting(output)) { signal_reconnect_success(output); os_atomic_set_bool(&output->reconnecting, false); } else { signal_start(output); } return true; }
bool obs_output_begin_data_capture(obs_output_t *output, uint32_t flags) { bool encoded, has_video, has_audio, has_service; if (!obs_output_valid(output, "obs_output_begin_data_capture")) return false; if (delay_active(output)) return begin_delayed_capture(output); if (active(output)) return false; output->total_frames = 0; convert_flags(output, flags, &encoded, &has_video, &has_audio, &has_service); if (!can_begin_data_capture(output, encoded, has_video, has_audio, has_service)) return false; os_atomic_set_bool(&output->data_active, true); hook_data_capture(output, encoded, has_video, has_audio); if (has_service) obs_service_activate(output->service); do_output_signal(output, "activate"); os_atomic_set_bool(&output->active, true); if (reconnecting(output)) { signal_reconnect_success(output); os_atomic_set_bool(&output->reconnecting, false); } else if (delay_active(output)) { do_output_signal(output, "starting"); } else { signal_start(output); } return true; }
bool obs_output_active(const obs_output_t *output) { return (output != NULL) ? (active(output) || reconnecting(output)) : false; }
int Irc::Session::qt_metacall(QMetaObject::Call _c, int _id, void **_a) { _id = QObject::qt_metacall(_c, _id, _a); if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod) { switch (_id) { case 0: connected(); break; case 1: welcomed(); break; case 2: reconnecting(); break; case 3: disconnected(); break; case 4: bufferAdded((*reinterpret_cast< Irc::Buffer*(*)>(_a[1]))); break; case 5: bufferRemoved((*reinterpret_cast< Irc::Buffer*(*)>(_a[1]))); break; case 6: capabilitiesListed((*reinterpret_cast< const QStringList(*)>(_a[1]))); break; case 7: capabilitiesAcked((*reinterpret_cast< const QStringList(*)>(_a[1]))); break; case 8: capabilitiesNotAcked((*reinterpret_cast< const QStringList(*)>(_a[1]))); break; case 9: msgJoined((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); break; case 10: msgParted((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2])),(*reinterpret_cast< const QString(*)>(_a[3]))); break; case 11: msgQuit((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); break; case 12: msgNickChanged((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); break; case 13: msgModeChanged((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2])),(*reinterpret_cast< const QString(*)>(_a[3])),(*reinterpret_cast< const QString(*)>(_a[4]))); break; case 14: msgTopicChanged((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2])),(*reinterpret_cast< const QString(*)>(_a[3]))); break; case 15: msgInvited((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2])),(*reinterpret_cast< const QString(*)>(_a[3]))); break; case 16: msgKicked((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2])),(*reinterpret_cast< const QString(*)>(_a[3])),(*reinterpret_cast< const QString(*)>(_a[4]))); break; case 17: msgMessageReceived((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2])),(*reinterpret_cast< const QString(*)>(_a[3]))); break; case 18: msgNoticeReceived((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2])),(*reinterpret_cast< const QString(*)>(_a[3]))); break; case 19: msgCtcpRequestReceived((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); break; case 20: msgCtcpReplyReceived((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); break; case 21: msgCtcpActionReceived((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2])),(*reinterpret_cast< const QString(*)>(_a[3]))); break; case 22: msgNumericMessageReceived((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< uint(*)>(_a[2])),(*reinterpret_cast< const QStringList(*)>(_a[3]))); break; case 23: msgUnknownMessageReceived((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QStringList(*)>(_a[2]))); break; case 24: connectToServer((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< quint16(*)>(_a[2]))); break; case 25: connectToServer((*reinterpret_cast< const QString(*)>(_a[1]))); break; case 26: connectToServer(); break; case 27: reconnectToServer(); break; case 28: disconnectFromServer(); break; case 29: { bool _r = raw((*reinterpret_cast< const QString(*)>(_a[1]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 30: { bool _r = motd(); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 31: { bool _r = join((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 32: { bool _r = join((*reinterpret_cast< const QString(*)>(_a[1]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 33: { bool _r = part((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 34: { bool _r = part((*reinterpret_cast< const QString(*)>(_a[1]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 35: { bool _r = quit((*reinterpret_cast< const QString(*)>(_a[1]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 36: { bool _r = quit(); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 37: { bool _r = names((*reinterpret_cast< const QString(*)>(_a[1]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 38: { bool _r = list((*reinterpret_cast< const QString(*)>(_a[1]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 39: { bool _r = list(); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 40: { bool _r = whois((*reinterpret_cast< const QString(*)>(_a[1]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 41: { bool _r = whowas((*reinterpret_cast< const QString(*)>(_a[1]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 42: { bool _r = mode((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 43: { bool _r = mode((*reinterpret_cast< const QString(*)>(_a[1]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 44: { bool _r = topic((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 45: { bool _r = topic((*reinterpret_cast< const QString(*)>(_a[1]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 46: { bool _r = invite((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 47: { bool _r = kick((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2])),(*reinterpret_cast< const QString(*)>(_a[3]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 48: { bool _r = kick((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 49: { bool _r = message((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 50: { bool _r = notice((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 51: { bool _r = ctcpAction((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 52: { bool _r = ctcpRequest((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 53: { bool _r = ctcpReply((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 54: requestCapabilities((*reinterpret_cast< const QStringList(*)>(_a[1]))); break; case 55: clearCapabilities(); break; case 56: { bool _r = sendRaw((*reinterpret_cast< const QString(*)>(_a[1]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 57: { bool _r = cmdJoin((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 58: { bool _r = cmdJoin((*reinterpret_cast< const QString(*)>(_a[1]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 59: { bool _r = cmdPart((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 60: { bool _r = cmdPart((*reinterpret_cast< const QString(*)>(_a[1]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 61: { bool _r = cmdQuit((*reinterpret_cast< const QString(*)>(_a[1]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 62: { bool _r = cmdQuit(); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 63: { bool _r = cmdNames((*reinterpret_cast< const QString(*)>(_a[1]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 64: { bool _r = cmdList((*reinterpret_cast< const QString(*)>(_a[1]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 65: { bool _r = cmdList(); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 66: { bool _r = cmdWhois((*reinterpret_cast< const QString(*)>(_a[1]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 67: { bool _r = cmdMode((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 68: { bool _r = cmdMode((*reinterpret_cast< const QString(*)>(_a[1]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 69: { bool _r = cmdTopic((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 70: { bool _r = cmdTopic((*reinterpret_cast< const QString(*)>(_a[1]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 71: { bool _r = cmdInvite((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 72: { bool _r = cmdKick((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2])),(*reinterpret_cast< const QString(*)>(_a[3]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 73: { bool _r = cmdKick((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 74: { bool _r = cmdMessage((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 75: { bool _r = cmdNotice((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 76: { bool _r = cmdCtcpAction((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 77: { bool _r = cmdCtcpRequest((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 78: { bool _r = cmdCtcpReply((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; } break; case 79: d_func()->_q_connected(); break; case 80: d_func()->_q_disconnected(); break; case 81: d_func()->_q_reconnect(); break; case 82: d_func()->_q_error(); break; case 83: d_func()->_q_state((*reinterpret_cast< QAbstractSocket::SocketState(*)>(_a[1]))); break; case 84: d_func()->_q_readData(); break; case 85: d_func()->_q_joined((*reinterpret_cast< const QString(*)>(_a[1]))); break; case 86: d_func()->_q_parted((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); break; case 87: d_func()->_q_quit((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); break; case 88: d_func()->_q_nickChanged((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); break; case 89: d_func()->_q_modeChanged((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2])),(*reinterpret_cast< const QString(*)>(_a[3]))); break; case 90: d_func()->_q_topicChanged((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); break; case 91: d_func()->_q_invited((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2])),(*reinterpret_cast< const QString(*)>(_a[3]))); break; case 92: d_func()->_q_kicked((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2])),(*reinterpret_cast< const QString(*)>(_a[3]))); break; case 93: d_func()->_q_messageReceived((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); break; case 94: d_func()->_q_noticeReceived((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); break; case 95: d_func()->_q_ctcpRequestReceived((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); break; case 96: d_func()->_q_ctcpReplyReceived((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); break; case 97: d_func()->_q_ctcpActionReceived((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2]))); break; case 98: d_func()->_q_numericMessageReceived((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< uint(*)>(_a[2])),(*reinterpret_cast< const QStringList(*)>(_a[3]))); break; case 99: d_func()->_q_unknownMessageReceived((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QStringList(*)>(_a[2]))); break; default: ; } _id -= 100; } #ifndef QT_NO_PROPERTIES else if (_c == QMetaObject::ReadProperty) { void *_v = _a[0]; switch (_id) { case 0: *reinterpret_cast< QStringList*>(_v) = autoJoinChannels(); break; case 1: *reinterpret_cast< int*>(_v) = autoReconnectDelay(); break; case 2: *reinterpret_cast< QByteArray*>(_v) = encoding(); break; case 3: *reinterpret_cast< QString*>(_v) = host(); break; case 4: *reinterpret_cast< QString*>(_v) = ident(); break; case 5: *reinterpret_cast< QString*>(_v) = nick(); break; case 6: *reinterpret_cast<int*>(_v) = QFlag(options()); break; case 7: *reinterpret_cast< QString*>(_v) = password(); break; case 8: *reinterpret_cast< quint16*>(_v) = port(); break; case 9: *reinterpret_cast< QString*>(_v) = realName(); break; case 10: *reinterpret_cast< QStringList*>(_v) = supportedCapabilities(); break; case 11: *reinterpret_cast< QStringList*>(_v) = enabledCapabilities(); break; } _id -= 12; } else if (_c == QMetaObject::WriteProperty) { void *_v = _a[0]; switch (_id) { case 0: setAutoJoinChannels(*reinterpret_cast< QStringList*>(_v)); break; case 1: setAutoReconnectDelay(*reinterpret_cast< int*>(_v)); break; case 2: setEncoding(*reinterpret_cast< QByteArray*>(_v)); break; case 3: setHost(*reinterpret_cast< QString*>(_v)); break; case 4: setIdent(*reinterpret_cast< QString*>(_v)); break; case 5: setNick(*reinterpret_cast< QString*>(_v)); break; case 6: setOptions(QFlag(*reinterpret_cast<int*>(_v))); break; case 7: setPassword(*reinterpret_cast< QString*>(_v)); break; case 8: setPort(*reinterpret_cast< quint16*>(_v)); break; case 9: setRealName(*reinterpret_cast< QString*>(_v)); break; } _id -= 12; } else if (_c == QMetaObject::ResetProperty) { _id -= 12; } else if (_c == QMetaObject::QueryPropertyDesignable) { _id -= 12; } else if (_c == QMetaObject::QueryPropertyScriptable) { _id -= 12; } else if (_c == QMetaObject::QueryPropertyStored) { _id -= 12; } else if (_c == QMetaObject::QueryPropertyEditable) { _id -= 12; } else if (_c == QMetaObject::QueryPropertyUser) { _id -= 12; } #endif // QT_NO_PROPERTIES return _id; }